[gtk+/gestures] Be careful about the list of event controllers
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gestures] Be careful about the list of event controllers
- Date: Fri, 9 May 2014 20:57:20 +0000 (UTC)
commit f97f1113bf0895fadffc9bcc9fc0fd1322a37ed6
Author: Matthias Clasen <mclasen redhat com>
Date: Fri May 9 15:53:27 2014 -0400
Be careful about the list of event controllers
We can end up with _gtk_widget_remove_controller getting called
while we are iterating over the list in _gtk_widget_run_controllers.
To avoid trouble, only mark the event controller as dead by
setting data->controller to NULL, and defer the actual freeing
and list manipulation to the loop in _gtk_widget_run_controllers.
Update other places that operate on controllers to handle
data->controller being NULL.
gtk/gtkwidget.c | 32 +++++++++++++++++++++-----------
1 files changed, 21 insertions(+), 11 deletions(-)
---
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 99cacca..35dfd94 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -7223,7 +7223,8 @@ _gtk_widget_get_controllers_evmask (GtkWidget *widget)
for (l = priv->event_controllers; l; l = l->next)
{
data = l->data;
- evmask |= gtk_event_controller_get_event_mask (GTK_EVENT_CONTROLLER (data->controller));
+ if (data->controller)
+ evmask |= gtk_event_controller_get_event_mask (GTK_EVENT_CONTROLLER (data->controller));
}
return evmask;
@@ -7242,12 +7243,21 @@ _gtk_widget_run_controllers (GtkWidget *widget,
priv = widget->priv;
g_object_ref (widget);
- for (l = priv->event_controllers; l; l = l->next)
+ l = priv->event_controllers;
+ while (l != NULL)
{
+ GList *next = l->next;
data = l->data;
- if (phase == data->phase)
+ if (data->controller == NULL)
+ {
+ priv->event_controllers = g_list_delete_link (priv->event_controllers, l);
+ g_free (data);
+ }
+ else if (data->phase == phase)
handled |= gtk_event_controller_handle_event (data->controller, event);
+
+ l = next;
}
g_object_unref (widget);
@@ -11714,6 +11724,7 @@ gtk_widget_dispose (GObject *object)
{
GtkWidget *widget = GTK_WIDGET (object);
GtkWidgetPrivate *priv = widget->priv;
+ GList *l;
if (priv->parent)
gtk_container_remove (GTK_CONTAINER (priv->parent), widget);
@@ -11736,11 +11747,14 @@ gtk_widget_dispose (GObject *object)
while (priv->attached_windows)
gtk_window_set_attached_to (priv->attached_windows->data, NULL);
- while (priv->event_controllers)
+ for (l = priv->event_controllers; l; l = l->next)
{
- EventControllerData *data = priv->event_controllers->data;
- _gtk_widget_remove_controller (widget, data->controller);
+ EventControllerData *data = l->data;
+ if (data->controller)
+ _gtk_widget_remove_controller (widget, data->controller);
}
+ g_list_free_full (priv->event_controllers, g_free);
+ priv->event_controllers = NULL;
G_OBJECT_CLASS (gtk_widget_parent_class)->dispose (object);
}
@@ -16771,19 +16785,15 @@ _gtk_widget_remove_controller (GtkWidget *widget,
GtkEventController *controller)
{
EventControllerData *data;
- GtkWidgetPrivate *priv;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
- priv = widget->priv;
data = _gtk_widget_has_controller (widget, controller);
if (!data)
return;
- priv->event_controllers = g_list_remove (priv->event_controllers, data);
-
if (g_signal_handler_is_connected (widget, data->grab_notify_id))
g_signal_handler_disconnect (widget, data->grab_notify_id);
@@ -16791,5 +16801,5 @@ _gtk_widget_remove_controller (GtkWidget *widget,
g_signal_handler_disconnect (data->controller, data->sequence_state_changed_id);
gtk_event_controller_reset (GTK_EVENT_CONTROLLER (data->controller));
g_object_unref (data->controller);
- g_free (data);
+ data->controller = NULL;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]