X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtksizerequest.c;h=0ce86bd66fc95b849c98347619791f28898604b8;hb=2cfc56ced81d801669deb3a429a00e25769e5a70;hp=b27fd05f173d8db93d76478075791d0f533624cc;hpb=82ae7b77cafad6c9370eb2d6ec56b14731147928;p=~andy%2Fgtk diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c index b27fd05f1..0ce86bd66 100644 --- a/gtk/gtksizerequest.c +++ b/gtk/gtksizerequest.c @@ -16,9 +16,7 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include @@ -29,169 +27,9 @@ #include "gtkintl.h" #include "gtkprivate.h" #include "gtksizegroup-private.h" +#include "gtksizerequestcacheprivate.h" #include "gtkwidgetprivate.h" - -/* looks for a cached size request for this for_size. If not - * found, returns the oldest entry so it can be overwritten - * - * Note that this caching code was originally derived from - * the Clutter toolkit. - */ - - -/* This function checks if 'request_needed' flag is present - * and resets the cache state if a request is needed for - * a given orientation. - */ -static SizeRequestCache * -init_cache (GtkWidget *widget, - GtkSizeGroupMode orientation) -{ - GtkSizeRequestMode mode; - SizeRequestCache *cache; - - cache = _gtk_widget_peek_request_cache (widget); - - if (orientation == GTK_SIZE_GROUP_HORIZONTAL && - _gtk_widget_get_width_request_needed (widget)) - { - mode = gtk_widget_get_request_mode (widget); - - if (mode == GTK_SIZE_REQUEST_CONSTANT_SIZE) - { - if (cache->sizes) - { - g_slice_free (ContextualSizes, cache->sizes); - cache->sizes = NULL; - } - } - else - { - if (!cache->sizes) - cache->sizes = g_slice_new0 (ContextualSizes); - - memset (cache->sizes->widths, 0x0, GTK_SIZE_REQUEST_CACHED_SIZES * sizeof (SizeRequest)); - cache->sizes->cached_widths = 0; - cache->sizes->last_cached_width = 0; - } - - cache->cached_width.minimum_size = -1; - cache->cached_width.natural_size = -1; - } - else if (orientation == GTK_SIZE_GROUP_VERTICAL && - _gtk_widget_get_height_request_needed (widget)) - { - mode = gtk_widget_get_request_mode (widget); - - if (mode == GTK_SIZE_REQUEST_CONSTANT_SIZE) - { - if (cache->sizes) - { - g_slice_free (ContextualSizes, cache->sizes); - cache->sizes = NULL; - } - } - else - { - if (!cache->sizes) - cache->sizes = g_slice_new0 (ContextualSizes); - - memset (cache->sizes->heights, 0x0, GTK_SIZE_REQUEST_CACHED_SIZES * sizeof (SizeRequest)); - cache->sizes->cached_heights = 0; - cache->sizes->last_cached_height = 0; - } - - cache->cached_height.minimum_size = -1; - cache->cached_height.natural_size = -1; - } - - return cache; -} - -static gboolean -get_cached_size (GtkWidget *widget, - GtkSizeGroupMode orientation, - gint for_size, - CachedSize **result) -{ - SizeRequestCache *cache; - SizeRequest *cached_sizes; - guint i, n_sizes; - - cache = init_cache (widget, orientation); - - if (for_size < 0) - { - if (orientation == GTK_SIZE_GROUP_HORIZONTAL) - *result = &cache->cached_width; - else - *result = &cache->cached_height; - - if ((*result)->minimum_size < 0) - return FALSE; - else - return TRUE; - } - - if (orientation == GTK_SIZE_GROUP_HORIZONTAL) - { - cached_sizes = cache->sizes->widths; - n_sizes = cache->sizes->cached_widths; - } - else - { - cached_sizes = cache->sizes->heights; - n_sizes = cache->sizes->cached_widths; - } - - /* Search for an already cached size */ - for (i = 0; i < n_sizes; i++) - { - if (cached_sizes[i].for_size == for_size) - { - *result = &cached_sizes[i].cached_size; - return TRUE; - } - } - - /* If not found, pull a new size from the cache, the returned size cache - * will immediately be used to cache the new computed size so we go ahead - * and increment the last_cached_width/height right away */ - if (orientation == GTK_SIZE_GROUP_HORIZONTAL) - { - if (cache->sizes->cached_widths < GTK_SIZE_REQUEST_CACHED_SIZES) - { - cache->sizes->cached_widths++; - cache->sizes->last_cached_width = cache->sizes->cached_widths - 1; - } - else - { - if (++cache->sizes->last_cached_width == GTK_SIZE_REQUEST_CACHED_SIZES) - cache->sizes->last_cached_width = 0; - } - - cache->sizes->widths[cache->sizes->last_cached_width].for_size = for_size; - *result = &cache->sizes->widths[cache->sizes->last_cached_width].cached_size; - } - else /* GTK_SIZE_GROUP_VERTICAL */ - { - if (cache->sizes->cached_heights < GTK_SIZE_REQUEST_CACHED_SIZES) - { - cache->sizes->cached_heights++; - cache->sizes->last_cached_height = cache->sizes->cached_heights - 1; - } - else - { - if (++cache->sizes->last_cached_height == GTK_SIZE_REQUEST_CACHED_SIZES) - cache->sizes->last_cached_height = 0; - } - - cache->sizes->heights[cache->sizes->last_cached_height].for_size = for_size; - *result = &cache->sizes->heights[cache->sizes->last_cached_height].cached_size; - } - - return FALSE; -} +#include "deprecated/gtkstyle.h" #ifndef G_DISABLE_CHECKS @@ -200,7 +38,7 @@ static GQuark recursion_check_quark = 0; static void push_recursion_check (GtkWidget *widget, - GtkSizeGroupMode orientation, + GtkOrientation orientation, gint for_size) { #ifndef G_DISABLE_CHECKS @@ -212,7 +50,7 @@ push_recursion_check (GtkWidget *widget, previous_method = g_object_get_qdata (G_OBJECT (widget), recursion_check_quark); - if (orientation == GTK_SIZE_GROUP_HORIZONTAL) + if (orientation == GTK_ORIENTATION_HORIZONTAL) { method = for_size < 0 ? "get_width" : "get_width_for_height"; } @@ -238,37 +76,52 @@ push_recursion_check (GtkWidget *widget, static void pop_recursion_check (GtkWidget *widget, - GtkSizeGroupMode orientation) + GtkOrientation orientation) { #ifndef G_DISABLE_CHECKS g_object_set_qdata (G_OBJECT (widget), recursion_check_quark, NULL); #endif } -/* This is the main function that checks for a cached size and - * possibly queries the widget class to compute the size if it's - * not cached. If the for_size here is -1, then get_preferred_width() - * or get_preferred_height() will be used. - */ +static const char * +get_vfunc_name (GtkOrientation orientation, + gint for_size) +{ + if (orientation == GTK_ORIENTATION_HORIZONTAL) + return for_size < 0 ? "get_preferred_width" : "get_preferred_width_for_height"; + else + return for_size < 0 ? "get_preferred_height" : "get_preferred_height_for_width"; +} + static void -compute_size_for_orientation (GtkWidget *widget, - GtkSizeGroupMode orientation, - gint for_size, - gint *minimum_size, - gint *natural_size) +gtk_widget_query_size_for_orientation (GtkWidget *widget, + GtkOrientation orientation, + gint for_size, + gint *minimum_size, + gint *natural_size) { - CachedSize *cached_size; - gboolean found_in_cache = FALSE; - gint adjusted_min, adjusted_natural; + SizeRequestCache *cache; + gint min_size = 0; + gint nat_size = 0; + gboolean found_in_cache; - found_in_cache = get_cached_size (widget, orientation, for_size, &cached_size); + if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE) + for_size = -1; + cache = _gtk_widget_peek_request_cache (widget); + found_in_cache = _gtk_size_request_cache_lookup (cache, + orientation, + for_size, + &min_size, + &nat_size); + if (!found_in_cache) { - gint min_size = 0; - gint nat_size = 0; + gint adjusted_min, adjusted_natural, adjusted_for_size = for_size; - if (orientation == GTK_SIZE_GROUP_HORIZONTAL) + gtk_widget_ensure_style (widget); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) { if (for_size < 0) { @@ -292,11 +145,11 @@ compute_size_for_orientation (GtkWidget *widget, &minimum_height, &natural_height, &ignored_position, - &for_size); + &adjusted_for_size); push_recursion_check (widget, orientation, for_size); GTK_WIDGET_GET_CLASS (widget)->get_preferred_width_for_height (widget, - MAX (for_size, minimum_height), + MAX (adjusted_for_size, minimum_height), &min_size, &nat_size); pop_recursion_check (widget, orientation); } @@ -311,9 +164,9 @@ compute_size_for_orientation (GtkWidget *widget, } else { - int ignored_position = 0; - int minimum_width; - int natural_width; + gint ignored_position = 0; + gint minimum_width; + gint natural_width; /* Pull the base natural width from the cache as it's needed to adjust * the proposed 'for_size' */ @@ -325,11 +178,11 @@ compute_size_for_orientation (GtkWidget *widget, &minimum_width, &natural_width, &ignored_position, - &for_size); + &adjusted_for_size); push_recursion_check (widget, orientation, for_size); GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget, - MAX (for_size, minimum_width), + MAX (adjusted_for_size, minimum_width), &min_size, &nat_size); pop_recursion_check (widget, orientation); } @@ -337,80 +190,124 @@ compute_size_for_orientation (GtkWidget *widget, if (min_size > nat_size) { - g_warning ("%s %p reported min size %d and natural size %d; natural size must be >= min size", - G_OBJECT_TYPE_NAME (widget), widget, min_size, nat_size); + g_warning ("%s %p reported min size %d and natural size %d in %s(); natural size must be >= min size", + G_OBJECT_TYPE_NAME (widget), widget, min_size, nat_size, get_vfunc_name (orientation, for_size)); } - cached_size->minimum_size = min_size; - cached_size->natural_size = nat_size; - - if (orientation == GTK_SIZE_GROUP_HORIZONTAL) - _gtk_widget_set_width_request_needed (widget, FALSE); - else - _gtk_widget_set_height_request_needed (widget, FALSE); - - adjusted_min = cached_size->minimum_size; - adjusted_natural = cached_size->natural_size; + adjusted_min = min_size; + adjusted_natural = nat_size; GTK_WIDGET_GET_CLASS (widget)->adjust_size_request (widget, - orientation == GTK_SIZE_GROUP_HORIZONTAL ? - GTK_ORIENTATION_HORIZONTAL : - GTK_ORIENTATION_VERTICAL, + orientation, &adjusted_min, &adjusted_natural); - if (adjusted_min < cached_size->minimum_size || - adjusted_natural < cached_size->natural_size) + if (adjusted_min < min_size || + adjusted_natural < nat_size) { g_warning ("%s %p adjusted size %s min %d natural %d must not decrease below min %d natural %d", G_OBJECT_TYPE_NAME (widget), widget, - orientation == GTK_SIZE_GROUP_VERTICAL ? "vertical" : "horizontal", + orientation == GTK_ORIENTATION_VERTICAL ? "vertical" : "horizontal", adjusted_min, adjusted_natural, - cached_size->minimum_size, cached_size->natural_size); + min_size, nat_size); /* don't use the adjustment */ } else if (adjusted_min > adjusted_natural) { g_warning ("%s %p adjusted size %s min %d natural %d original min %d natural %d has min greater than natural", G_OBJECT_TYPE_NAME (widget), widget, - orientation == GTK_SIZE_GROUP_VERTICAL ? "vertical" : "horizontal", + orientation == GTK_ORIENTATION_VERTICAL ? "vertical" : "horizontal", adjusted_min, adjusted_natural, - cached_size->minimum_size, cached_size->natural_size); + min_size, nat_size); /* don't use the adjustment */ } else { /* adjustment looks good */ - cached_size->minimum_size = adjusted_min; - cached_size->natural_size = adjusted_natural; + min_size = adjusted_min; + nat_size = adjusted_natural; } - /* Update size-groups with our request and update our cached requests - * with the size-group values in a single pass. - */ - _gtk_size_group_bump_requisition (widget, - orientation, - &cached_size->minimum_size, - &cached_size->natural_size); + _gtk_size_request_cache_commit (cache, + orientation, + for_size, + min_size, + nat_size); } if (minimum_size) - *minimum_size = cached_size->minimum_size; + *minimum_size = min_size; if (natural_size) - *natural_size = cached_size->natural_size; + *natural_size = nat_size; - g_assert (cached_size->minimum_size <= cached_size->natural_size); + g_assert (min_size <= nat_size); GTK_NOTE (SIZE_REQUEST, g_print ("[%p] %s\t%s: %d is minimum %d and natural: %d (hit cache: %s)\n", widget, G_OBJECT_TYPE_NAME (widget), - orientation == GTK_SIZE_GROUP_HORIZONTAL ? + orientation == GTK_ORIENTATION_HORIZONTAL ? "width for height" : "height for width" , - for_size, - cached_size->minimum_size, - cached_size->natural_size, + for_size, min_size, nat_size, found_in_cache ? "yes" : "no")); +} +/* This is the main function that checks for a cached size and + * possibly queries the widget class to compute the size if it's + * not cached. If the for_size here is -1, then get_preferred_width() + * or get_preferred_height() will be used. + */ +void +_gtk_widget_compute_size_for_orientation (GtkWidget *widget, + GtkOrientation orientation, + gint for_size, + gint *minimum, + gint *natural) +{ + GHashTable *widgets; + GHashTableIter iter; + gpointer key; + gint min_result = 0, nat_result = 0; + + if (!gtk_widget_get_visible (widget) && !gtk_widget_is_toplevel (widget)) + { + if (minimum) + *minimum = 0; + if (natural) + *natural = 0; + return; + } + + if (G_LIKELY (!_gtk_widget_get_sizegroups (widget))) + { + gtk_widget_query_size_for_orientation (widget, orientation, for_size, minimum, natural); + return; + } + + widgets = _gtk_size_group_get_widget_peers (widget, orientation); + + g_hash_table_foreach (widgets, (GHFunc) g_object_ref, NULL); + + g_hash_table_iter_init (&iter, widgets); + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + GtkWidget *tmp_widget = key; + gint min_dimension, nat_dimension; + + gtk_widget_query_size_for_orientation (tmp_widget, orientation, for_size, &min_dimension, &nat_dimension); + + min_result = MAX (min_result, min_dimension); + nat_result = MAX (nat_result, nat_dimension); + } + + g_hash_table_foreach (widgets, (GHFunc) g_object_unref, NULL); + + g_hash_table_destroy (widgets); + + if (minimum) + *minimum = min_result; + + if (natural) + *natural = nat_result; } /** @@ -432,9 +329,19 @@ compute_size_for_orientation (GtkWidget *widget, GtkSizeRequestMode gtk_widget_get_request_mode (GtkWidget *widget) { - g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH); + SizeRequestCache *cache; + + g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_SIZE_REQUEST_CONSTANT_SIZE); - return GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget); + cache = _gtk_widget_peek_request_cache (widget); + + if (!cache->request_mode_valid) + { + cache->request_mode = GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget); + cache->request_mode_valid = TRUE; + } + + return cache->request_mode; } /** @@ -464,8 +371,11 @@ gtk_widget_get_preferred_width (GtkWidget *widget, g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (minimum_width != NULL || natural_width != NULL); - compute_size_for_orientation (widget, GTK_SIZE_GROUP_HORIZONTAL, - -1, minimum_width, natural_width); + _gtk_widget_compute_size_for_orientation (widget, + GTK_ORIENTATION_HORIZONTAL, + -1, + minimum_width, + natural_width); } @@ -495,8 +405,11 @@ gtk_widget_get_preferred_height (GtkWidget *widget, g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (minimum_height != NULL || natural_height != NULL); - compute_size_for_orientation (widget, GTK_SIZE_GROUP_VERTICAL, - -1, minimum_height, natural_height); + _gtk_widget_compute_size_for_orientation (widget, + GTK_ORIENTATION_VERTICAL, + -1, + minimum_height, + natural_height); } @@ -529,12 +442,11 @@ gtk_widget_get_preferred_width_for_height (GtkWidget *widget, g_return_if_fail (minimum_width != NULL || natural_width != NULL); g_return_if_fail (height >= 0); - if (GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE) - compute_size_for_orientation (widget, GTK_SIZE_GROUP_HORIZONTAL, - -1, minimum_width, natural_width); - else - compute_size_for_orientation (widget, GTK_SIZE_GROUP_HORIZONTAL, - height, minimum_width, natural_width); + _gtk_widget_compute_size_for_orientation (widget, + GTK_ORIENTATION_HORIZONTAL, + height, + minimum_width, + natural_width); } /** @@ -565,12 +477,11 @@ gtk_widget_get_preferred_height_for_width (GtkWidget *widget, g_return_if_fail (minimum_height != NULL || natural_height != NULL); g_return_if_fail (width >= 0); - if (GTK_WIDGET_GET_CLASS (widget)->get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE) - compute_size_for_orientation (widget, GTK_SIZE_GROUP_VERTICAL, - -1, minimum_height, natural_height); - else - compute_size_for_orientation (widget, GTK_SIZE_GROUP_VERTICAL, - width, minimum_height, natural_height); + _gtk_widget_compute_size_for_orientation (widget, + GTK_ORIENTATION_VERTICAL, + width, + minimum_height, + natural_height); } /**