From: Christoffer Aasted Date: Fri, 24 Jul 2026 20:31:48 +0000 (+0000) Subject: patch 9.2.0851: Focus autocommands triggered inconsistently X-Git-Tag: v9.2.0851^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=729c10990ddfe736af2cc04ed7721dd64d4a5a49;p=thirdparty%2Fvim.git patch 9.2.0851: Focus autocommands triggered inconsistently Problem: Focus autocommands triggered inconsistently Solution: Suppress dialog-generated focus events while a dialog is active and on X11 ignore the restoring focus_in_event() from closing a dialog (Christoffer Aasted). closes: #20780 Signed-off-by: Christoffer Aasted Signed-off-by: Christian Brabandt --- diff --git a/src/gui.c b/src/gui.c index 3457c88f13..0e1306c868 100644 --- a/src/gui.c +++ b/src/gui.c @@ -485,6 +485,11 @@ gui_init_check(void) result = OK; #else # ifdef FEAT_GUI_GTK + gui.is_x11 = false; +# ifdef FEAT_GUI_DIALOG + gui.dialogs_active = 0; + gui.dialog_focus_pending = 0; +# endif # ifdef GDK_WINDOWING_WAYLAND gui.is_wayland = false; # endif @@ -4905,7 +4910,11 @@ gui_focus_change(int in_focus) // Put events in the input queue only when allowed. // ui_focus_change() isn't called directly, because it invokes // autocommands and that must not happen asynchronously. - if (!hold_gui_events) + if (!hold_gui_events +# if defined(FEAT_GUI_GTK) && defined(FEAT_GUI_DIALOG) + && gui.dialogs_active == 0 +# endif + ) { char_u bytes[3]; diff --git a/src/gui.h b/src/gui.h index aa9f94ec9b..1fadca0f01 100644 --- a/src/gui.h +++ b/src/gui.h @@ -412,6 +412,14 @@ typedef struct Gui char_u *browse_fname; // file name from filedlg guint32 event_time; +# ifdef FEAT_GUI_DIALOG + // Multiple dialogs not allowed, just tracked for future use. + int dialogs_active; // number of active GUI dialogs + + // X11 focus_in_event() by dialogs, ignored to match wayland. + int dialog_focus_pending; +# endif + bool is_x11; // active gdk backend in gtk is x11 # ifdef GDK_WINDOWING_WAYLAND bool is_wayland; // active gdk backend in gtk is wayland # endif diff --git a/src/gui_gtk.c b/src/gui_gtk.c index 13eaf70a73..620480289b 100644 --- a/src/gui_gtk.c +++ b/src/gui_gtk.c @@ -1709,6 +1709,10 @@ gui_mch_dialog(int type, // type of dialog int response; DialogInfo dialoginfo; + ++gui.dialogs_active; + if (gui.is_x11) + ++gui.dialog_focus_pending; + dialog = create_message_dialog(type, title, message); dialoginfo.dialog = GTK_DIALOG(dialog); dialog_add_buttons(GTK_DIALOG(dialog), buttons); @@ -1796,6 +1800,7 @@ gui_mch_dialog(int type, // type of dialog gtk_widget_destroy(dialog); } + --gui.dialogs_active; return response > 0 ? response : 0; } diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index b12f4b22c3..098892d5c1 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -1080,7 +1080,12 @@ focus_in_event(GtkWidget *widget, GdkEventFocus *event UNUSED, gpointer data UNUSED) { - gui_focus_change(TRUE); +#ifdef FEAT_GUI_DIALOG + if (gui.is_x11 && gui.dialog_focus_pending > 0) + --gui.dialog_focus_pending; + else +#endif + gui_focus_change(TRUE); if (blink_state == BLINK_NONE) gui_mch_start_blink(); @@ -4136,6 +4141,7 @@ gui_mch_init(void) #if GTK_CHECK_VERSION(3,4,0) if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) { + gui.is_x11 = true; // for X11, if we were using smooth scroll events, we // would get an scroll without deltas on the very first user scroll* and // get both "unsmooth" scroll and smooth scroll events after diff --git a/src/version.c b/src/version.c index 028ab88800..422af5fda4 100644 --- a/src/version.c +++ b/src/version.c @@ -758,6 +758,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 851, /**/ 850, /**/