]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0590: GTK4: drawing area loses focus shape on popup menu open v9.2.0590
authorFoxe Chen <chen.foxe@gmail.com>
Wed, 3 Jun 2026 18:19:42 +0000 (18:19 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 3 Jun 2026 18:19:42 +0000 (18:19 +0000)
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 <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/gui_gtk4.c
src/version.c

index c3c6f6cc695e48c81a2efff773230606022d5e2b..1c2c935d621999d1e116a4a03b31da4eb2b80019 100644 (file)
@@ -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)
index 9b38c195f83eea4610e1bd80d40ccd56abf4c896..bc577f9ba0deeb96ae4b42bf4d19281a9f1e2abc 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    590,
 /**/
     589,
 /**/