[gtk/wip/baedert/for-master: 43/46] widget: Save controllers list in a GPtrArray



commit f56507ef32512943a2380a7707b9ef910a44b58b
Author: Timm Bäder <mail baedert org>
Date:   Sun Apr 26 19:45:34 2020 +0200

    widget: Save controllers list in a GPtrArray

 gtk/gtkwidget.c        | 232 ++++++++++++++++++++++++++++++++-----------------
 gtk/gtkwidgetprivate.h |   2 +-
 2 files changed, 151 insertions(+), 83 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index a77b086908..25a10dd3ef 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -818,11 +818,14 @@ gtk_widget_real_grab_notify (GtkWidget *widget,
                              gboolean   was_grabbed)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
+  int i;
+
+  if (!priv->controllers)
+    return;
 
-  for (l = g_list_last (priv->event_controllers); l; l = l->prev)
+  for (i = (int)priv->controllers->len - 1; i >= 0; i--)
     {
-      GtkEventController *controller = l->data;
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
       GdkDevice *device = NULL;
 
       if (GTK_IS_GESTURE (controller))
@@ -839,14 +842,19 @@ static void
 gtk_widget_real_root (GtkWidget *widget)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
+  guint i;
 
   gtk_widget_forall (widget, (GtkCallback) gtk_widget_root, NULL);
 
-  for (l = priv->event_controllers; l; l = l->next)
+  if (!priv->controllers)
+    return;
+
+  for (i = 0; i < priv->controllers->len; i++)
     {
-      if (GTK_IS_SHORTCUT_CONTROLLER (l->data))
-        gtk_shortcut_controller_root (GTK_SHORTCUT_CONTROLLER (l->data));
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
+
+      if (GTK_IS_SHORTCUT_CONTROLLER (controller))
+        gtk_shortcut_controller_root (GTK_SHORTCUT_CONTROLLER (controller));
     }
 }
 
@@ -854,12 +862,17 @@ static void
 gtk_widget_real_unroot (GtkWidget *widget)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
+  guint i;
 
-  for (l = priv->event_controllers; l; l = l->next)
+  if (priv->controllers)
     {
-      if (GTK_IS_SHORTCUT_CONTROLLER (l->data))
-        gtk_shortcut_controller_unroot (GTK_SHORTCUT_CONTROLLER (l->data));
+      for (i = 0; i < priv->controllers->len; i++)
+        {
+          GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
+
+          if (GTK_IS_SHORTCUT_CONTROLLER (controller))
+            gtk_shortcut_controller_unroot (GTK_SHORTCUT_CONTROLLER (controller));
+        }
     }
 
   gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
@@ -2043,13 +2056,15 @@ _gtk_widget_get_last_event (GtkWidget         *widget,
                             GtkWidget        **target)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GtkEventController *controller;
   GdkEvent *event;
-  GList *l;
+  guint i;
+
+  if (!priv->controllers)
+    goto out;
 
-  for (l = priv->event_controllers; l; l = l->next)
+  for (i = 0; i < priv->controllers->len; i++)
     {
-      controller = l->data;
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
       if (!GTK_IS_GESTURE (controller))
         continue;
@@ -2062,6 +2077,7 @@ _gtk_widget_get_last_event (GtkWidget         *widget,
         }
     }
 
+out:
   *target = NULL;
   return NULL;
 }
@@ -2072,7 +2088,6 @@ _gtk_widget_get_emulating_sequence (GtkWidget         *widget,
                                     GdkEventSequence **sequence_out)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
 
   *sequence_out = sequence;
 
@@ -2090,12 +2105,13 @@ _gtk_widget_get_emulating_sequence (GtkWidget         *widget,
            gdk_touch_event_get_emulating_pointer (last_event))
         return TRUE;
     }
-  else
+  else if (priv->controllers)
     {
+      guint i;
       /* For a NULL(pointer) sequence, find the pointer emulating one */
-      for (l = priv->event_controllers; l; l = l->next)
+      for (i = 0; i < priv->controllers->len; i++)
         {
-          GtkEventController *controller = l->data;
+          GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
           if (!GTK_IS_GESTURE (controller))
             continue;
@@ -2115,14 +2131,17 @@ gtk_widget_needs_press_emulation (GtkWidget        *widget,
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
   gboolean sequence_press_handled = FALSE;
-  GList *l;
+  guint i;
+
+  if (!priv->controllers)
+    return FALSE;
 
   /* Check whether there is any remaining gesture in
    * the capture phase that handled the press event
    */
-  for (l = priv->event_controllers; l; l = l->next)
+  for (i = 0; i < priv->controllers->len; i++)
     {
-      GtkEventController *controller = l->data;
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
       GtkPropagationPhase phase;
       GtkGesture *gesture;
 
@@ -2152,11 +2171,13 @@ _gtk_widget_set_sequence_state_internal (GtkWidget             *widget,
   gboolean emulates_pointer, sequence_handled = FALSE;
   GdkEvent *mimic_event;
   GtkWidget *target;
-  GList *group = NULL, *l;
+  GList *group = NULL;
   GdkEventSequence *seq;
   gint n_handled = 0;
+  guint i;
 
-  if (!priv->event_controllers && state != GTK_EVENT_SEQUENCE_CLAIMED)
+  if (state != GTK_EVENT_SEQUENCE_CLAIMED &&
+      (!priv->controllers || priv->controllers->len == 0))
     return TRUE;
 
   if (emitter)
@@ -2165,15 +2186,14 @@ _gtk_widget_set_sequence_state_internal (GtkWidget             *widget,
   emulates_pointer = _gtk_widget_get_emulating_sequence (widget, sequence, &seq);
   mimic_event = _gtk_widget_get_last_event (widget, seq, &target);
 
-  for (l = priv->event_controllers; l; l = l->next)
+  for (i = 0; i < priv->controllers->len; i++)
     {
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
       GtkEventSequenceState gesture_state;
-      GtkEventController *controller;
       GtkGesture *gesture;
       gboolean retval;
 
       seq = sequence;
-      controller = l->data;
       gesture_state = state;
 
       if (!GTK_IS_GESTURE (controller))
@@ -2241,17 +2261,19 @@ _gtk_widget_cancel_sequence (GtkWidget        *widget,
   gboolean emulates_pointer;
   gboolean handled = FALSE;
   GdkEventSequence *seq;
-  GList *l;
+  guint i;
+
+  if (!priv->controllers)
+    return FALSE;
 
   emulates_pointer = _gtk_widget_get_emulating_sequence (widget, sequence, &seq);
 
-  for (l = priv->event_controllers; l; l = l->next)
+  for (i = 0; i < priv->controllers->len; i++)
     {
-      GtkEventController *controller;
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
       GtkGesture *gesture;
 
       seq = sequence;
-      controller = l->data;
 
       if (!GTK_IS_GESTURE (controller))
         continue;
@@ -4479,25 +4501,25 @@ gtk_widget_run_controllers (GtkWidget           *widget,
                            GtkPropagationPhase  phase)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GtkEventController *controller;
   gboolean handled = FALSE;
-  GList *l;
+  guint i;
+
+  if (!priv->controllers)
+    return FALSE;
 
   g_object_ref (widget);
 
-  l = priv->event_controllers;
-  while (l != NULL)
+  for (i = 0; i < priv->controllers->len; i++)
     {
-      GList *next = l->next;
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
       if (!WIDGET_REALIZED_FOR_EVENT (widget, event))
         break;
 
-      controller = l->data;
-
       if (controller == NULL)
         {
-          priv->event_controllers = g_list_delete_link (priv->event_controllers, l);
+          g_ptr_array_remove_index (priv->controllers, i);
+          i--; /* Need to check this index again */
         }
       else
         {
@@ -4523,8 +4545,6 @@ gtk_widget_run_controllers (GtkWidget           *widget,
                 break;
             }
         }
-
-      l = next;
     }
 
   g_object_unref (widget);
@@ -4539,14 +4559,16 @@ gtk_widget_handle_crossing (GtkWidget             *widget,
                             double                 y)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
+  guint i;
+
+  if (!priv->controllers)
+    return;
 
   g_object_ref (widget);
 
-  for (l = priv->event_controllers; l; l = l->next)
+  for (i = 0; i < priv->controllers->len; i++)
     {
-      GtkEventController *controller = l->data;
-
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
       gtk_event_controller_handle_crossing (controller, crossing, x, y);
     }
 
@@ -5697,7 +5719,7 @@ gtk_widget_set_sensitive (GtkWidget *widget,
                          gboolean   sensitive)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
+  guint i;
 
   g_return_if_fail (GTK_IS_WIDGET (widget));
 
@@ -5708,11 +5730,14 @@ gtk_widget_set_sensitive (GtkWidget *widget,
 
   priv->sensitive = sensitive;
 
-  for (l = priv->event_controllers; l; l = l->next)
+  if (priv->controllers)
     {
-      GtkEventController *controller = l->data;
+      for (i = 0; i < priv->controllers->len; i++)
+        {
+          GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
-      gtk_event_controller_reset (controller);
+          gtk_event_controller_reset (controller);
+        }
     }
 
   if (priv->parent == NULL
@@ -7344,12 +7369,19 @@ gtk_widget_real_destroy (GtkWidget *object)
   destroy_surface_transform_data (widget);
 }
 
+static void
+gtk_widget_unset_controller (GtkWidget          *widget,
+                             GtkEventController *controller)
+{
+  GTK_EVENT_CONTROLLER_GET_CLASS (controller)->unset_widget (controller);
+  g_object_unref (controller);
+}
+
 static void
 gtk_widget_finalize (GObject *object)
 {
   GtkWidget *widget = GTK_WIDGET (object);
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
 
   gtk_grab_remove (widget);
 
@@ -7366,18 +7398,17 @@ gtk_widget_finalize (GObject *object)
 
   _gtk_size_request_cache_free (&priv->requests);
 
-  l = priv->event_controllers;
-  while (l)
+  if (priv->controllers)
     {
-      GList *next = l->next;
-      GtkEventController *controller = l->data;
-
-      if (controller)
-        gtk_widget_remove_controller (widget, controller);
+      guint i;
+      for (i = 0; i < priv->controllers->len; i++)
+        {
+          GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
-      l = next;
+          gtk_widget_unset_controller (widget, controller);
+        }
+      g_ptr_array_free (priv->controllers, TRUE);
     }
-  g_assert (priv->event_controllers == NULL);
 
   if (_gtk_widget_get_first_child (widget) != NULL)
     {
@@ -7774,7 +7805,6 @@ gtk_widget_propagate_state (GtkWidget          *widget,
       if (!gtk_widget_is_sensitive (widget))
         gtk_widget_reset_controllers (widget);
 
-
       /* Make sure to only propagate the right states further */
       child_data.old_scale_factor = new_scale_factor;
       child_data.flags_to_set = data->flags_to_set & GTK_STATE_FLAGS_DO_SET_PROPAGATE;
@@ -11370,7 +11400,10 @@ gtk_widget_add_controller (GtkWidget          *widget,
 
   GTK_EVENT_CONTROLLER_GET_CLASS (controller)->set_widget (controller, widget);
 
-  priv->event_controllers = g_list_prepend (priv->event_controllers, controller);
+  if (G_UNLIKELY (!priv->controllers))
+    priv->controllers = g_ptr_array_new ();
+
+  g_ptr_array_add (priv->controllers, controller);
 
   if (priv->controller_observer)
     gtk_list_list_model_item_added_at (priv->controller_observer, 0);
@@ -11392,21 +11425,28 @@ gtk_widget_remove_controller (GtkWidget          *widget,
                               GtkEventController *controller)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *before, *list;
 
   g_return_if_fail (GTK_IS_WIDGET (widget));
   g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
   g_return_if_fail (gtk_event_controller_get_widget (controller) == widget);
 
-  GTK_EVENT_CONTROLLER_GET_CLASS (controller)->unset_widget (controller);
+  if (priv->controller_observer)
+    {
+      /* Here we care about the index */
+      guint index;
 
-  list = g_list_find (priv->event_controllers, controller);
-  before = list->prev;
-  priv->event_controllers = g_list_delete_link (priv->event_controllers, list);
-  g_object_unref (controller);
+      g_ptr_array_find (priv->controllers, controller, &index);
 
-  if (priv->controller_observer)
-    gtk_list_list_model_item_removed (priv->controller_observer, before);
+      gtk_list_list_model_item_removed_at (priv->controller_observer, index);
+      g_ptr_array_remove_index_fast (priv->controllers, index);
+    }
+  else
+    {
+      /* XXX _fast really possible? */
+      g_ptr_array_remove_fast (priv->controllers, controller);
+    }
+
+  gtk_widget_unset_controller (widget, controller);
 }
 
 gboolean
@@ -11417,11 +11457,14 @@ _gtk_widget_consumes_motion (GtkWidget        *widget,
 
   while (widget != NULL && !GTK_IS_WINDOW (widget))
     {
-      GList *l;
+      guint i;
 
-      for (l = priv->event_controllers; l; l = l->next)
+      if (!priv->controllers)
+        goto next;
+
+      for (i = 0; i < priv->controllers->len; i++)
         {
-          GtkEventController *controller = l->data;
+          GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
           if (controller == NULL ||
               !GTK_IS_GESTURE (controller))
@@ -11434,6 +11477,7 @@ _gtk_widget_consumes_motion (GtkWidget        *widget,
             return TRUE;
         }
 
+next:
       widget = priv->parent;
       priv = gtk_widget_get_instance_private (widget);
     }
@@ -11445,12 +11489,15 @@ void
 gtk_widget_reset_controllers (GtkWidget *widget)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
-  GList *l;
+  guint i;
+
+  if (!priv->controllers)
+    return;
 
   /* Reset all controllers */
-  for (l = priv->event_controllers; l; l = l->next)
+  for (i = 0; i < priv->controllers->len; i++)
     {
-      GtkEventController *controller = l->data;
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
       if (controller == NULL)
         continue;
@@ -11466,13 +11513,13 @@ gtk_widget_list_controllers (GtkWidget           *widget,
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
   GPtrArray *controllers = g_ptr_array_new ();
-  GList *l;
+  guint i;
 
   g_assert (out_n_controllers);
 
-  for (l = priv->event_controllers; l; l = l->next)
+    for (i = 0; i < priv->controllers->len; i++)
     {
-      GtkEventController *controller = l->data;
+      GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
 
       if (gtk_event_controller_get_propagation_phase (controller) == phase)
         g_ptr_array_add (controllers, controller);
@@ -11709,28 +11756,49 @@ gtk_widget_controller_observer_destroyed (gpointer widget)
 static gpointer
 gtk_widget_controller_list_get_first (gpointer widget)
 {
-  return GTK_WIDGET (widget)->priv->event_controllers;
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+  if (priv->controllers)
+    return g_ptr_array_index (priv->controllers, 0);
+
+  return NULL;
 }
 
 static gpointer
 gtk_widget_controller_list_get_next (gpointer item,
                                      gpointer widget)
 {
-  return g_list_next (item);
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+  guint index;
+
+  g_ptr_array_find (priv->controllers, item, &index);
+
+  if (index + 1 <= priv->controllers->len - 1)
+    return g_ptr_array_index (priv->controllers, index + 1);
+
+  return NULL;
 }
 
 static gpointer
 gtk_widget_controller_list_get_prev (gpointer item,
                                      gpointer widget)
 {
-  return g_list_previous (item);
+  GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+  guint index;
+
+  g_ptr_array_find (priv->controllers, item, &index);
+
+  if (index >= 0)
+    return g_ptr_array_index (priv->controllers, index - 1);
+
+  return NULL;
 }
 
 static gpointer
 gtk_widget_controller_list_get_item (gpointer item,
                                      gpointer widget)
 {
-  return g_object_ref (((GList *) item)->data);
+  return item;
 }
 
 /**
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 5085353525..5a92e75e5d 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -174,7 +174,7 @@ struct _GtkWidgetPrivate
 
   GSList *paintables;
 
-  GList *event_controllers;
+  GPtrArray *controllers;
 
   AtkObject *accessible;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]