patch 9.2.0590: GTK4: drawing area loses focus shape on popup menu open

Commit: 
https://github.com/vim/vim/commit/7d8971edf470132e9dde3ae01be6830cfed70773
Author: Foxe Chen <[email protected]>
Date:   Wed Jun 3 18:19:42 2026 +0000

    patch 9.2.0590: GTK4: drawing area loses focus shape on popup menu open
    
    Problem:  GTK4: any focus change on the drawarea turns the cursor
              into an outline, including transient focus movement to a
              GUI popup menu and back.  The cursor flashes outline-shape
              during menu interaction.  The GTK3 GUI does not have this
              problem because it ties the cursor shape to toplevel window
              focus, not drawarea focus.
    Solution: Gate focus_in_event() and focus_out_event() on
              gtk_window_is_active() of the toplevel window, matching
              GTK3 behaviour. Reverts v9.2.0588 (Foxe Chen).
    
    closes: #20415
    
    Signed-off-by: Foxe Chen <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/gui_gtk4.c b/src/gui_gtk4.c
index c3c6f6cc6..1c2c935d6 100644
--- a/src/gui_gtk4.c
+++ b/src/gui_gtk4.c
@@ -271,13 +271,9 @@ static void button_press_event(GtkGestureClick *gesture, 
int n_press, double x,
 static void button_release_event(GtkGestureClick *gesture, int n_press, double 
x, double y, gpointer data);
 static void motion_notify_event(GtkEventControllerMotion *controller, double 
x, double y, gpointer data);
 static void enter_notify_event(GtkEventControllerMotion *controller, double x, 
double y, gpointer data);
-static void leave_notify_event(GtkEventControllerMotion *controller, gpointer 
data);
 static gboolean scroll_event(GtkEventControllerScroll *controller, double dx, 
double dy, gpointer data);
 static void focus_in_event(GtkEventControllerFocus *controller, gpointer data);
 static void focus_out_event(GtkEventControllerFocus *controller, gpointer 
data);
-#ifdef FEAT_MENU
-static gboolean menubar_popover_closed_hook(GSignalInvocationHint *ihint, 
guint n_param_values, const GValue *param_values, gpointer data);
-#endif
 #ifdef FEAT_DND
 static gboolean drop_cb(GtkDropTarget *target, const GValue *value, double x, 
double y, gpointer data);
 #endif
@@ -479,20 +475,6 @@ gui_mch_init(void)
        gtk_widget_set_visible(gui.menubar, FALSE);
        gtk_box_append(GTK_BOX(vbox), gui.menubar);
     }
-    // Return keyboard focus to the drawing area when a menubar popover
-    // closes (issue #20274).  GtkPopoverMenuBar owns its popovers
-    // privately, so attach via an emission hook on GtkPopover::closed
-    // and filter for popovers under our menubar inside the callback.
-    {
-       GTypeClass *cls = g_type_class_ref(GTK_TYPE_POPOVER);
-       guint sig_id = g_signal_lookup("closed", GTK_TYPE_POPOVER);
-
-       if (sig_id != 0)
-           g_signal_add_emission_hook(sig_id, 0,
-                   menubar_popover_closed_hook, NULL, NULL);
-       if (cls != NULL)
-           g_type_class_unref(cls);
-    }
 #endif
 
 #ifdef FEAT_TOOLBAR
@@ -574,8 +556,6 @@ gui_mch_init(void)
                         G_CALLBACK(motion_notify_event), NULL);
        g_signal_connect(motion, "enter",
                         G_CALLBACK(enter_notify_event), NULL);
-       g_signal_connect(motion, "leave",
-                        G_CALLBACK(leave_notify_event), NULL);
        gtk_widget_add_controller(gui.drawarea, motion);
     }
 
@@ -1869,9 +1849,6 @@ motion_notify_event(GtkEventControllerMotion *controller 
UNUSED,
 enter_notify_event(GtkEventControllerMotion *controller UNUSED,
        double x UNUSED, double y UNUSED, gpointer data UNUSED)
 {
-    if (blink_state == BLINK_NONE)
-       gui_mch_start_blink();
-
     prev_mouse_x = x;
     prev_mouse_y = y;
 
@@ -1880,14 +1857,6 @@ enter_notify_event(GtkEventControllerMotion *controller 
UNUSED,
        gtk_widget_grab_focus(gui.drawarea);
 }
 
-    static void
-leave_notify_event(GtkEventControllerMotion *controller UNUSED,
-       gpointer data UNUSED)
-{
-    if (blink_state != BLINK_NONE)
-       gui_mch_stop_blink(TRUE);
-}
-
     static gboolean
 scroll_event(GtkEventControllerScroll *controller UNUSED,
        double dx UNUSED, double dy, gpointer data UNUSED)
@@ -1927,61 +1896,25 @@ scroll_event(GtkEventControllerScroll *controller 
UNUSED,
 focus_in_event(GtkEventControllerFocus *controller UNUSED,
        gpointer data UNUSED)
 {
-    gui_focus_change(TRUE);
-    if (blink_state == BLINK_NONE)
-       gui_mch_start_blink();
+    if (gtk_window_is_active(GTK_WINDOW(gui.mainwin)))
+    {
+       gui_focus_change(TRUE);
+       if (blink_state == BLINK_NONE)
+           gui_mch_start_blink();
+    }
 }
 
     static void
 focus_out_event(GtkEventControllerFocus *controller UNUSED,
        gpointer data UNUSED)
 {
-    gui_focus_change(FALSE);
-    if (blink_state != BLINK_NONE)
-       gui_mch_stop_blink(TRUE);
-}
-
-#ifdef FEAT_MENU
-    static gboolean
-grab_drawarea_focus_idle(gpointer data UNUSED)
-{
-    if (gui.drawarea != NULL && !gtk_widget_has_focus(gui.drawarea))
-       gtk_widget_grab_focus(gui.drawarea);
-    return G_SOURCE_REMOVE;
-}
-
-    static gboolean
-menubar_popover_closed_hook(GSignalInvocationHint *ihint UNUSED,
-       guint n_param_values, const GValue *param_values,
-       gpointer data UNUSED)
-{
-    GObject    *obj;
-    GtkWidget  *popover;
-    GtkWidget  *parent;
-
-    if (n_param_values < 1 || gui.menubar == NULL || gui.drawarea == NULL)
-       return TRUE;
-    obj = g_value_get_object(&param_values[0]);
-    if (!GTK_IS_POPOVER(obj))
-       return TRUE;
-    popover = GTK_WIDGET(obj);
-
-    // Only react to popovers that descend from the menubar.
-    for (parent = gtk_widget_get_parent(popover);
-           parent != NULL;
-           parent = gtk_widget_get_parent(parent))
+    if (!gtk_window_is_active(GTK_WINDOW(gui.mainwin)))
     {
-       if (parent != gui.menubar)
-           continue;
-       // Defer the grab to the next main loop iteration; calling it
-       // synchronously while GTK is still completing the popover close
-       // has no effect (issue #20274).
-       g_idle_add(grab_drawarea_focus_idle, NULL);
-       break;
+       gui_focus_change(FALSE);
+       if (blink_state != BLINK_NONE)
+           gui_mch_stop_blink(TRUE);
     }
-    return TRUE;       // keep the emission hook installed
 }
-#endif
 
     static void
 drawarea_realize_cb(GtkWidget *widget UNUSED, gpointer data UNUSED)
diff --git a/src/version.c b/src/version.c
index 9b38c195f..bc577f9ba 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    590,
 /**/
     589,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1wUqLs-003pnE-Fk%40256bit.org.

Raspunde prin e-mail lui