widget: Save controllers list in a GPtrArray

This commit is contained in:
Timm Bäder 2020-04-26 19:45:34 +02:00
parent ef623aaabc
commit 4b9e5304cc
2 changed files with 152 additions and 84 deletions

View File

@ -818,11 +818,14 @@ gtk_widget_real_grab_notify (GtkWidget *widget,
gboolean was_grabbed) gboolean was_grabbed)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l; int i;
for (l = g_list_last (priv->event_controllers); l; l = l->prev) if (!priv->controllers)
return;
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; GdkDevice *device = NULL;
if (GTK_IS_GESTURE (controller)) if (GTK_IS_GESTURE (controller))
@ -839,14 +842,19 @@ static void
gtk_widget_real_root (GtkWidget *widget) gtk_widget_real_root (GtkWidget *widget)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l; guint i;
gtk_widget_forall (widget, (GtkCallback) gtk_widget_root, NULL); 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)) GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
gtk_shortcut_controller_root (GTK_SHORTCUT_CONTROLLER (l->data));
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) gtk_widget_real_unroot (GtkWidget *widget)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (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)) for (i = 0; i < priv->controllers->len; i++)
gtk_shortcut_controller_unroot (GTK_SHORTCUT_CONTROLLER (l->data)); {
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); gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
@ -2058,13 +2071,15 @@ _gtk_widget_get_last_event (GtkWidget *widget,
GtkWidget **target) GtkWidget **target)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkEventController *controller;
GdkEvent *event; GdkEvent *event;
GList *l; guint i;
for (l = priv->event_controllers; l; l = l->next) if (!priv->controllers)
goto out;
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)) if (!GTK_IS_GESTURE (controller))
continue; continue;
@ -2077,6 +2092,7 @@ _gtk_widget_get_last_event (GtkWidget *widget,
} }
} }
out:
*target = NULL; *target = NULL;
return NULL; return NULL;
} }
@ -2087,7 +2103,6 @@ _gtk_widget_get_emulating_sequence (GtkWidget *widget,
GdkEventSequence **sequence_out) GdkEventSequence **sequence_out)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l;
*sequence_out = sequence; *sequence_out = sequence;
@ -2105,12 +2120,13 @@ _gtk_widget_get_emulating_sequence (GtkWidget *widget,
gdk_touch_event_get_emulating_pointer (last_event)) gdk_touch_event_get_emulating_pointer (last_event))
return TRUE; return TRUE;
} }
else else if (priv->controllers)
{ {
guint i;
/* For a NULL(pointer) sequence, find the pointer emulating one */ /* 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)) if (!GTK_IS_GESTURE (controller))
continue; continue;
@ -2130,14 +2146,17 @@ gtk_widget_needs_press_emulation (GtkWidget *widget,
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
gboolean sequence_press_handled = FALSE; gboolean sequence_press_handled = FALSE;
GList *l; guint i;
if (!priv->controllers)
return FALSE;
/* Check whether there is any remaining gesture in /* Check whether there is any remaining gesture in
* the capture phase that handled the press event * 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; GtkPropagationPhase phase;
GtkGesture *gesture; GtkGesture *gesture;
@ -2167,11 +2186,13 @@ _gtk_widget_set_sequence_state_internal (GtkWidget *widget,
gboolean emulates_pointer, sequence_handled = FALSE; gboolean emulates_pointer, sequence_handled = FALSE;
GdkEvent *mimic_event; GdkEvent *mimic_event;
GtkWidget *target; GtkWidget *target;
GList *group = NULL, *l; GList *group = NULL;
GdkEventSequence *seq; GdkEventSequence *seq;
gint n_handled = 0; 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; return TRUE;
if (emitter) if (emitter)
@ -2180,15 +2201,14 @@ _gtk_widget_set_sequence_state_internal (GtkWidget *widget,
emulates_pointer = _gtk_widget_get_emulating_sequence (widget, sequence, &seq); emulates_pointer = _gtk_widget_get_emulating_sequence (widget, sequence, &seq);
mimic_event = _gtk_widget_get_last_event (widget, seq, &target); 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; GtkEventSequenceState gesture_state;
GtkEventController *controller;
GtkGesture *gesture; GtkGesture *gesture;
gboolean retval; gboolean retval;
seq = sequence; seq = sequence;
controller = l->data;
gesture_state = state; gesture_state = state;
if (!GTK_IS_GESTURE (controller)) if (!GTK_IS_GESTURE (controller))
@ -2256,17 +2276,19 @@ _gtk_widget_cancel_sequence (GtkWidget *widget,
gboolean emulates_pointer; gboolean emulates_pointer;
gboolean handled = FALSE; gboolean handled = FALSE;
GdkEventSequence *seq; GdkEventSequence *seq;
GList *l; guint i;
if (!priv->controllers)
return FALSE;
emulates_pointer = _gtk_widget_get_emulating_sequence (widget, sequence, &seq); 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; GtkGesture *gesture;
seq = sequence; seq = sequence;
controller = l->data;
if (!GTK_IS_GESTURE (controller)) if (!GTK_IS_GESTURE (controller))
continue; continue;
@ -4494,25 +4516,25 @@ gtk_widget_run_controllers (GtkWidget *widget,
GtkPropagationPhase phase) GtkPropagationPhase phase)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GtkEventController *controller;
gboolean handled = FALSE; gboolean handled = FALSE;
GList *l; guint i;
if (!priv->controllers)
return FALSE;
g_object_ref (widget); g_object_ref (widget);
l = priv->event_controllers; for (i = 0; i < priv->controllers->len; i++)
while (l != NULL)
{ {
GList *next = l->next; GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
if (!WIDGET_REALIZED_FOR_EVENT (widget, event)) if (!WIDGET_REALIZED_FOR_EVENT (widget, event))
break; break;
controller = l->data;
if (controller == NULL) 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 else
{ {
@ -4538,8 +4560,6 @@ gtk_widget_run_controllers (GtkWidget *widget,
break; break;
} }
} }
l = next;
} }
g_object_unref (widget); g_object_unref (widget);
@ -4554,14 +4574,16 @@ gtk_widget_handle_crossing (GtkWidget *widget,
double y) double y)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l; guint i;
if (!priv->controllers)
return;
g_object_ref (widget); 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); gtk_event_controller_handle_crossing (controller, crossing, x, y);
} }
@ -5712,7 +5734,7 @@ gtk_widget_set_sensitive (GtkWidget *widget,
gboolean sensitive) gboolean sensitive)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l; guint i;
g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GTK_IS_WIDGET (widget));
@ -5723,11 +5745,14 @@ gtk_widget_set_sensitive (GtkWidget *widget,
priv->sensitive = sensitive; 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 if (priv->parent == NULL
@ -7359,12 +7384,19 @@ gtk_widget_real_destroy (GtkWidget *object)
destroy_surface_transform_data (widget); 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 static void
gtk_widget_finalize (GObject *object) gtk_widget_finalize (GObject *object)
{ {
GtkWidget *widget = GTK_WIDGET (object); GtkWidget *widget = GTK_WIDGET (object);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l;
gtk_grab_remove (widget); gtk_grab_remove (widget);
@ -7381,18 +7413,17 @@ gtk_widget_finalize (GObject *object)
_gtk_size_request_cache_free (&priv->requests); _gtk_size_request_cache_free (&priv->requests);
l = priv->event_controllers; if (priv->controllers)
while (l)
{ {
GList *next = l->next; guint i;
GtkEventController *controller = l->data; for (i = 0; i < priv->controllers->len; i++)
{
GtkEventController *controller = g_ptr_array_index (priv->controllers, i);
if (controller) gtk_widget_unset_controller (widget, controller);
gtk_widget_remove_controller (widget, controller); }
g_ptr_array_free (priv->controllers, TRUE);
l = next;
} }
g_assert (priv->event_controllers == NULL);
if (_gtk_widget_get_first_child (widget) != NULL) if (_gtk_widget_get_first_child (widget) != NULL)
{ {
@ -7789,7 +7820,6 @@ gtk_widget_propagate_state (GtkWidget *widget,
if (!gtk_widget_is_sensitive (widget)) if (!gtk_widget_is_sensitive (widget))
gtk_widget_reset_controllers (widget); gtk_widget_reset_controllers (widget);
/* Make sure to only propagate the right states further */ /* Make sure to only propagate the right states further */
child_data.old_scale_factor = new_scale_factor; child_data.old_scale_factor = new_scale_factor;
child_data.flags_to_set = data->flags_to_set & GTK_STATE_FLAGS_DO_SET_PROPAGATE; child_data.flags_to_set = data->flags_to_set & GTK_STATE_FLAGS_DO_SET_PROPAGATE;
@ -11385,7 +11415,10 @@ gtk_widget_add_controller (GtkWidget *widget,
GTK_EVENT_CONTROLLER_GET_CLASS (controller)->set_widget (controller, 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) if (priv->controller_observer)
gtk_list_list_model_item_added_at (priv->controller_observer, 0); gtk_list_list_model_item_added_at (priv->controller_observer, 0);
@ -11407,21 +11440,28 @@ gtk_widget_remove_controller (GtkWidget *widget,
GtkEventController *controller) GtkEventController *controller)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); 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_WIDGET (widget));
g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller)); g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
g_return_if_fail (gtk_event_controller_get_widget (controller) == widget); g_return_if_fail (gtk_event_controller_get_widget (controller) == widget);
GTK_EVENT_CONTROLLER_GET_CLASS (controller)->unset_widget (controller);
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);
if (priv->controller_observer) if (priv->controller_observer)
gtk_list_list_model_item_removed (priv->controller_observer, before); {
/* Here we care about the index */
guint index;
g_ptr_array_find (priv->controllers, controller, &index);
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 gboolean
@ -11432,11 +11472,14 @@ _gtk_widget_consumes_motion (GtkWidget *widget,
while (widget != NULL && !GTK_IS_WINDOW (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 || if (controller == NULL ||
!GTK_IS_GESTURE (controller)) !GTK_IS_GESTURE (controller))
@ -11449,6 +11492,7 @@ _gtk_widget_consumes_motion (GtkWidget *widget,
return TRUE; return TRUE;
} }
next:
widget = priv->parent; widget = priv->parent;
priv = gtk_widget_get_instance_private (widget); priv = gtk_widget_get_instance_private (widget);
} }
@ -11460,12 +11504,15 @@ void
gtk_widget_reset_controllers (GtkWidget *widget) gtk_widget_reset_controllers (GtkWidget *widget)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l; guint i;
if (!priv->controllers)
return;
/* Reset all controllers */ /* 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) if (controller == NULL)
continue; continue;
@ -11481,13 +11528,13 @@ gtk_widget_list_controllers (GtkWidget *widget,
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GPtrArray *controllers = g_ptr_array_new (); GPtrArray *controllers = g_ptr_array_new ();
GList *l; guint i;
g_assert (out_n_controllers); 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) if (gtk_event_controller_get_propagation_phase (controller) == phase)
g_ptr_array_add (controllers, controller); g_ptr_array_add (controllers, controller);
@ -11724,28 +11771,49 @@ gtk_widget_controller_observer_destroyed (gpointer widget)
static gpointer static gpointer
gtk_widget_controller_list_get_first (gpointer widget) 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 static gpointer
gtk_widget_controller_list_get_next (gpointer item, gtk_widget_controller_list_get_next (gpointer item,
gpointer widget) 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 static gpointer
gtk_widget_controller_list_get_prev (gpointer item, gtk_widget_controller_list_get_prev (gpointer item,
gpointer widget) 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 static gpointer
gtk_widget_controller_list_get_item (gpointer item, gtk_widget_controller_list_get_item (gpointer item,
gpointer widget) gpointer widget)
{ {
return g_object_ref (((GList *) item)->data); return item;
} }
/** /**

View File

@ -174,7 +174,7 @@ struct _GtkWidgetPrivate
GSList *paintables; GSList *paintables;
GList *event_controllers; GPtrArray *controllers;
AtkObject *accessible; AtkObject *accessible;