]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0851: Focus autocommands triggered inconsistently v9.2.0851
authorChristoffer Aasted <dezzadk@gmail.com>
Fri, 24 Jul 2026 20:31:48 +0000 (20:31 +0000)
committerChristian Brabandt <cb@256bit.org>
Fri, 24 Jul 2026 20:31:48 +0000 (20:31 +0000)
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 <dezzadk@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/gui.c
src/gui.h
src/gui_gtk.c
src/gui_gtk_x11.c
src/version.c

index 3457c88f13d1af50acce90b5133dc24e4255a922..0e1306c868b5a3314875ed0ac83bb21925832c33 100644 (file)
--- 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];
 
index aa9f94ec9b45694ceefe829b39a09ebcfa2496b3..1fadca0f01f883af6cbf3a59869512ef6cbee2e3 100644 (file)
--- 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
index 13eaf70a7344ab46754fda5a24c4af5766ca5f08..620480289b98e649e5c6af06d100b3cf84ce0c82 100644 (file)
@@ -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;
 }
 
index b12f4b22c36a70a361c0047bda4a02b6c9b70f4b..098892d5c12268273b069fd4d1c34340f93686cf 100644 (file)
@@ -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
index 028ab88800dd3ab0fa89ef14b79c8af3af14f27c..422af5fda412809fdd36ccd9b69b72611db16535 100644 (file)
@@ -758,6 +758,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    851,
 /**/
     850,
 /**/