From 93e591fdf13065decc252a54b65b83c5e6f0075f Mon Sep 17 00:00:00 2001 From: Corey Berla Date: Mon, 24 Oct 2022 15:53:29 -0700 Subject: [PATCH] listbase: Use set_focus_child properly The EventControllerFocus on the list item, updates the list base focus tracker and scrolled to position any time the list item enters focus. This works when interacting within a single window, but has unexpected results when changing focus between multiple windows. Instead of using the focus controller workaround, just make gtk_list_base_update_focus_tracker the set_focus_child vfunc Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5433 Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5432 --- gtk/gtklistbase.c | 57 +++++++++++++++++++---------------------- gtk/gtklistitemwidget.c | 18 ------------- 2 files changed, 27 insertions(+), 48 deletions(-) diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index cedae1aa9b..1571be69c7 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -802,28 +802,6 @@ gtk_list_base_compute_scroll_align (GtkListBase *self, } } -static void -gtk_list_base_update_focus_tracker (GtkListBase *self) -{ - GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); - GtkWidget *focus_child; - guint pos; - - focus_child = gtk_widget_get_focus_child (GTK_WIDGET (self)); - if (!GTK_IS_LIST_ITEM_WIDGET (focus_child)) - return; - - pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (focus_child)); - if (pos != gtk_list_item_tracker_get_position (priv->item_manager, priv->focus)) - { - gtk_list_item_tracker_set_position (priv->item_manager, - priv->focus, - pos, - 0, - 0); - } -} - static void gtk_list_base_scroll_to_item (GtkListBase *self, guint pos) @@ -859,14 +837,6 @@ gtk_list_base_scroll_to_item (GtkListBase *self, pos, align_across, side_across, align_along, side_along); - - /* HACK HACK HACK - * - * GTK has no way to track the focused child. But we now that when a listitem - * gets focus, it calls this action. So we update our focus tracker from here - * because it's the closest we can get to accurate tracking. - */ - gtk_list_base_update_focus_tracker (self); } static void @@ -885,6 +855,32 @@ gtk_list_base_scroll_to_item_action (GtkWidget *widget, gtk_list_base_scroll_to_item (self, pos); } +static void +gtk_list_base_set_focus_child (GtkWidget *widget, + GtkWidget *child) +{ + GtkListBase *self = GTK_LIST_BASE (widget); + GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); + guint pos; + + GTK_WIDGET_CLASS (gtk_list_base_parent_class)->set_focus_child (widget, child); + + if (!GTK_IS_LIST_ITEM_WIDGET (child)) + return; + + pos = gtk_list_item_widget_get_position (GTK_LIST_ITEM_WIDGET (child)); + + if (pos != gtk_list_item_tracker_get_position (priv->item_manager, priv->focus)) + { + gtk_list_base_scroll_to_item (self, pos); + gtk_list_item_tracker_set_position (priv->item_manager, + priv->focus, + pos, + 0, + 0); + } +} + static void gtk_list_base_select_item_action (GtkWidget *widget, const char *action_name, @@ -1143,6 +1139,7 @@ gtk_list_base_class_init (GtkListBaseClass *klass) widget_class->focus = gtk_list_base_focus; widget_class->grab_focus = gtk_list_base_grab_focus; + widget_class->set_focus_child = gtk_list_base_set_focus_child; gobject_class->dispose = gtk_list_base_dispose; gobject_class->get_property = gtk_list_base_get_property; diff --git a/gtk/gtklistitemwidget.c b/gtk/gtklistitemwidget.c index 2fb5e1633c..d191150203 100644 --- a/gtk/gtklistitemwidget.c +++ b/gtk/gtklistitemwidget.c @@ -22,7 +22,6 @@ #include "gtklistitemwidgetprivate.h" #include "gtkbinlayout.h" -#include "gtkeventcontrollerfocus.h" #include "gtkeventcontrollermotion.h" #include "gtkgestureclick.h" #include "gtklistitemfactoryprivate.h" @@ -467,19 +466,6 @@ gtk_list_item_widget_click_gesture_released (GtkGestureClick *gesture, gtk_widget_unset_state_flags (GTK_WIDGET (self), GTK_STATE_FLAG_ACTIVE); } -static void -gtk_list_item_widget_enter_cb (GtkEventControllerFocus *controller, - GtkListItemWidget *self) -{ - GtkWidget *widget = GTK_WIDGET (self); - GtkListItemWidgetPrivate *priv = gtk_list_item_widget_get_instance_private (self); - - gtk_widget_activate_action (widget, - "list.scroll-to-item", - "u", - priv->position); -} - static void gtk_list_item_widget_hover_cb (GtkEventControllerMotion *controller, double x, @@ -531,10 +517,6 @@ gtk_list_item_widget_init (GtkListItemWidget *self) G_CALLBACK (gtk_list_item_widget_click_gesture_canceled), self); gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture)); - controller = gtk_event_controller_focus_new (); - g_signal_connect (controller, "enter", G_CALLBACK (gtk_list_item_widget_enter_cb), self); - gtk_widget_add_controller (GTK_WIDGET (self), controller); - controller = gtk_event_controller_motion_new (); g_signal_connect (controller, "enter", G_CALLBACK (gtk_list_item_widget_hover_cb), self); gtk_widget_add_controller (GTK_WIDGET (self), controller); -- 2.30.2