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 1f001a8f6a)

7081bfc6 listbase: Split scroll_to_item for reuse
93e591fd listbase: Use set_focus_child properly
This commit is contained in:
Benjamin Otte 2022-12-14 19:06:57 +00:00 committed by Corey Berla
parent 779f8063d3
commit 9df10fa96f
2 changed files with 45 additions and 58 deletions

View File

@ -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:

View File

@ -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);