diff options
author | Daniel Boles <dboles@src.gnome.org> | 2018-01-18 00:51:24 +0000 |
---|---|---|
committer | Daniel Boles <dboles@src.gnome.org> | 2018-01-22 19:10:58 +0000 |
commit | b91fc17a1911a479e058d1df3a24486faa473290 (patch) | |
tree | 473958948b6d37e3e25c43367a1bcbd781f5544c | |
parent | 37482c81c7ff25bed45f0ead15a610f888eddb43 (diff) | |
download | gtk+-b91fc17a1911a479e058d1df3a24486faa473290.tar.gz |
Widget: Don’t call reset() on NULL EventController
GtkGesture is a GtkEventController. gtk_event_controller_dispose() calls
_gtk_widget_remove_controller(). That NULLs the pointer-to-Controller in
our EventControllerData but does not delete said ECData from our GList.
Subsequently, if that same Widget gets unparent()ed, that method calls
unset_state_flags(), which leads to doing reset_controllers() if we are
insensitive. Now, unlike most most other loops over the GList of ECData,
reset_controllers() does not skip nodes whose pointer-to-Controller is
NULL. So, we call gtk_event_controller_reset(NULL) and get a CRITICAL.
This surfaced in a gtkmm program. The Gesture is destroyed before the
Widget. The Widget then gets dispose()d, which calls unparent()… boom.
I didn’t find an MCVE yet but would hope this logic is correct anyway:
The simplest fix is to make the loop in gtk_widget_reset_controllers()
skip GList nodes with a NULL Controller pointer, like most other such
loops, so we avoid passing the NULL to gtk_event_controller_reset().
In other, live cases, _gtk_widget_run_controllers() loops over the GList
and removes/frees nodes having NULL Controllers, so that should suffice.
But this clearly was not getting a chance to happen in the failing case.
https://bugzilla.gnome.org/show_bug.cgi?id=792624
-rw-r--r-- | gtk/gtkwidget.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 4ae273036e..b1386298bf 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -13891,6 +13891,10 @@ gtk_widget_reset_controllers (GtkWidget *widget) for (l = priv->event_controllers; l; l = l->next) { controller_data = l->data; + + if (controller_data->controller == NULL) + continue; + gtk_event_controller_reset (controller_data->controller); } } |