From 9df10fa96f25774dc52a29dafaf093c3be9202ac Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 14 Dec 2022 19:06:57 +0000 Subject: [PATCH] Merge branch 'wip/corey/listbase-focus' into 'main' listbase: Use set_focus_child properly Closes #5433 and #5432 See merge request GNOME/gtk!5169 (cherry picked from commit 1f001a8f6af1c761d8b47e9f5eb0e8936d77d92a) 7081bfc6 listbase: Split scroll_to_item for reuse 93e591fd listbase: Use set_focus_child properly --- gtk/gtklistbase.c | 85 ++++++++++++++++++++++------------------- gtk/gtklistitemwidget.c | 18 --------- 2 files changed, 45 insertions(+), 58 deletions(-) diff --git a/gtk/gtklistbase.c b/gtk/gtklistbase.c index 03bcb48288..1571be69c7 100644 --- a/gtk/gtklistbase.c +++ b/gtk/gtklistbase.c @@ -803,43 +803,13 @@ gtk_list_base_compute_scroll_align (GtkListBase *self, } static void -gtk_list_base_update_focus_tracker (GtkListBase *self) +gtk_list_base_scroll_to_item (GtkListBase *self, + guint pos) { - 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 (GtkWidget *widget, - const char *action_name, - GVariant *parameter) -{ - GtkListBase *self = GTK_LIST_BASE (widget); GtkListBasePrivate *priv = gtk_list_base_get_instance_private (self); int start, end; double align_along, align_across; GtkPackType side_along, side_across; - guint pos; - - if (!g_variant_check_format_string (parameter, "u", FALSE)) - return; - - g_variant_get (parameter, "u", &pos); /* figure out primary orientation and if position is valid */ if (!gtk_list_base_get_allocation_along (GTK_LIST_BASE (self), pos, &start, &end)) @@ -867,14 +837,48 @@ gtk_list_base_scroll_to_item (GtkWidget *widget, 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 +gtk_list_base_scroll_to_item_action (GtkWidget *widget, + const char *action_name, + GVariant *parameter) +{ + GtkListBase *self = GTK_LIST_BASE (widget); + guint pos; + + if (!g_variant_check_format_string (parameter, "u", FALSE)) + return; + + g_variant_get (parameter, "u", &pos); + + 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 @@ -1135,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; @@ -1179,7 +1184,7 @@ gtk_list_base_class_init (GtkListBaseClass *klass) gtk_widget_class_install_action (widget_class, "list.scroll-to-item", "u", - gtk_list_base_scroll_to_item); + gtk_list_base_scroll_to_item_action); /** * GtkListBase|list.select-item: 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);