From 8960d64cc687cb4c98381ff5bd7a6d04be9dde1d Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 5 Sep 2010 02:48:36 -0400 Subject: [PATCH] Warn about recursively calling size req wrappers on the same object and orientation We are not re-entrant and there is no reason for widgets to do this, most likely they'll just get unexpected bugs because the wrappers may modify the request. Computing the request should logically rely only on the widget itself, not on any adjustments caused by set_size_request, size groups, and so forth. https://bugzilla.gnome.org/show_bug.cgi?id=628829 --- gtk/gtksizerequest.c | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c index 7c67c7eab9..827265ef29 100644 --- a/gtk/gtksizerequest.c +++ b/gtk/gtksizerequest.c @@ -155,6 +155,57 @@ do_size_request (GtkWidget *widget, g_signal_emit_by_name (widget, "size-request", requisition); } +#ifndef G_DISABLE_CHECKS +static GQuark recursion_check_quark = 0; +#endif /* G_DISABLE_CHECKS */ + +static void +push_recursion_check (GtkSizeRequest *request, + GtkSizeGroupMode orientation, + gint for_size) +{ +#ifndef G_DISABLE_CHECKS + const char *previous_method; + const char *method; + + if (recursion_check_quark == 0) + recursion_check_quark = g_quark_from_static_string ("gtk-size-request-in-progress"); + + previous_method = g_object_get_qdata (G_OBJECT (request), recursion_check_quark); + + if (orientation == GTK_SIZE_GROUP_HORIZONTAL) + { + method = for_size < 0 ? "get_width" : "get_width_for_height"; + } + else + { + method = for_size < 0 ? "get_height" : "get_height_for_width"; + } + + if (previous_method != NULL) + { + g_warning ("%s %p: widget tried to gtk_size_request_%s inside " + " GtkSizeRequest::%s implementation. " + "Should just invoke GTK_SIZE_REQUEST_GET_IFACE(widget)->%s " + "directly rather than using gtk_size_request_%s", + G_OBJECT_TYPE_NAME (request), request, + method, previous_method, + method, method); + } + + g_object_set_qdata (G_OBJECT (request), recursion_check_quark, (char*) method); +#endif /* G_DISABLE_CHECKS */ +} + +static void +pop_recursion_check (GtkSizeRequest *request, + GtkSizeGroupMode orientation) +{ +#ifndef G_DISABLE_CHECKS + g_object_set_qdata (G_OBJECT (request), recursion_check_quark, NULL); +#endif +} + static void compute_size_for_orientation (GtkSizeRequest *request, GtkSizeGroupMode orientation, @@ -207,6 +258,7 @@ compute_size_for_orientation (GtkSizeRequest *request, /* Unconditional size request runs but is often unhandled. */ do_size_request (widget, &requisition); + push_recursion_check (request, orientation, for_size); if (orientation == GTK_SIZE_GROUP_HORIZONTAL) { requisition_size = requisition.width; @@ -227,6 +279,7 @@ compute_size_for_orientation (GtkSizeRequest *request, GTK_SIZE_REQUEST_GET_IFACE (request)->get_height_for_width (request, for_size, &min_size, &nat_size); } + pop_recursion_check (request, orientation); if (min_size > nat_size) {