From: Foxe Chen Date: Wed, 3 Jun 2026 18:19:42 +0000 (+0000) Subject: patch 9.2.0590: GTK4: drawing area loses focus shape on popup menu open X-Git-Tag: v9.2.0590^0 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=7d8971edf470132e9dde3ae01be6830cfed70773;p=thirdparty%2Fvim.git 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 Signed-off-by: Christian Brabandt --- diff --git a/src/gui_gtk4.c b/src/gui_gtk4.c index c3c6f6cc69..1c2c935d62 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(¶m_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 9b38c195f8..bc577f9ba0 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, /**/