Merge branch 'wip/corey/listbase-focus' into 'main'
authorBenjamin Otte <otte.benjamin@googlemail.com>
Wed, 14 Dec 2022 19:06:57 +0000 (19:06 +0000)
committerCorey Berla <corey@berla.me>
Thu, 15 Dec 2022 03:21:54 +0000 (22:21 -0500)
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
gtk/gtklistitemwidget.c

index 03bcb48288cec10164bb72e017b893c1845974eb..1571be69c72592435c0e8d88db0bcf63832403dc 100644 (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:
index 2fb5e1633c5634c7703993b9e25416a62ee3c9d5..d19115020313fb782cb2be368d3b05efa2c1f2b7 100644 (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);