Пример #1
0
void
_gtk_widget_free_cached_sizes (GtkWidget *widget)
{
  SizeRequestCache   *cache;

  cache = _gtk_widget_peek_request_cache (widget);

  clear_cache (cache, GTK_SIZE_GROUP_HORIZONTAL);
  clear_cache (cache, GTK_SIZE_GROUP_VERTICAL);
}
Пример #2
0
/* 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)
{
  SizeRequestCache *cache;

  cache = _gtk_widget_peek_request_cache (widget);

  if (_gtk_widget_get_width_request_needed (widget))
    clear_cache (cache, GTK_SIZE_GROUP_HORIZONTAL);
  
  if (_gtk_widget_get_height_request_needed (widget))
    clear_cache (cache, GTK_SIZE_GROUP_VERTICAL);

  return cache;
}
Пример #3
0
/**
 * gtk_widget_get_request_mode:
 * @widget: a #GtkWidget instance
 *
 * Gets whether the widget prefers a height-for-width layout
 * or a width-for-height layout.
 *
 * <note><para>#GtkBin widgets generally propagate the preference of
 * their child, container widgets need to request something either in
 * context of their children or in context of their allocation
 * capabilities.</para></note>
 *
 * Returns: The #GtkSizeRequestMode preferred by @widget.
 *
 * Since: 3.0
 */
GtkSizeRequestMode
gtk_widget_get_request_mode (GtkWidget *widget)
{
  SizeRequestCache *cache;

  g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_SIZE_REQUEST_CONSTANT_SIZE);

  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;
}
Пример #4
0
static void
real_queue_resize (GtkWidget          *widget,
		   GtkQueueResizeFlags flags)
{
  GtkWidget *container;

  _gtk_widget_set_alloc_needed (widget, TRUE);
  _gtk_size_request_cache_clear (_gtk_widget_peek_request_cache (widget));

  container = gtk_widget_get_parent (widget);
  if (!container &&
      gtk_widget_is_toplevel (widget) && GTK_IS_CONTAINER (widget))
    container = widget;

  if (container)
    {
      if (flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY)
	_gtk_container_resize_invalidate (GTK_CONTAINER (container));
      else
	_gtk_container_queue_resize (GTK_CONTAINER (container));
    }
}
Пример #5
0
static void
gtk_widget_query_size_for_orientation (GtkWidget        *widget,
                                       GtkOrientation    orientation,
                                       gint              for_size,
                                       gint             *minimum_size,
                                       gint             *natural_size)
{
  SizeRequestCache *cache;
  gint min_size = 0;
  gint nat_size = 0;
  gboolean found_in_cache;

  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 adjusted_min, adjusted_natural, adjusted_for_size = for_size;

      G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
      gtk_widget_ensure_style (widget);
      G_GNUC_END_IGNORE_DEPRECATIONS;

      if (orientation == GTK_ORIENTATION_HORIZONTAL)
        {
          if (for_size < 0)
            {
	      push_recursion_check (widget, orientation, for_size);
              GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, &min_size, &nat_size);
	      pop_recursion_check (widget, orientation);
            }
          else
            {
              gint ignored_position = 0;
              gint minimum_height;
              gint natural_height;

	      /* Pull the base natural height from the cache as it's needed to adjust
	       * the proposed 'for_size' */
	      gtk_widget_get_preferred_height (widget, &minimum_height, &natural_height);

              /* convert for_size to unadjusted height (for_size is a proposed allocation) */
              GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget,
                                                                     GTK_ORIENTATION_VERTICAL,
                                                                     &minimum_height,
								     &natural_height,
                                                                     &ignored_position,
                                                                     &adjusted_for_size);

	      push_recursion_check (widget, orientation, for_size);
              GTK_WIDGET_GET_CLASS (widget)->get_preferred_width_for_height (widget, 
									     MAX (adjusted_for_size, minimum_height),
									     &min_size, &nat_size);
	      pop_recursion_check (widget, orientation);
            }
        }
      else
        {
          if (for_size < 0)
            {
	      push_recursion_check (widget, orientation, for_size);
              GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, &min_size, &nat_size);
	      pop_recursion_check (widget, orientation);
            }
          else
            {
              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' */
	      gtk_widget_get_preferred_width (widget, &minimum_width, &natural_width);

              /* convert for_size to unadjusted width (for_size is a proposed allocation) */
              GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget,
                                                                     GTK_ORIENTATION_HORIZONTAL,
								     &minimum_width,
                                                                     &natural_width,
                                                                     &ignored_position,
                                                                     &adjusted_for_size);

	      push_recursion_check (widget, orientation, for_size);
              GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget, 
									     MAX (adjusted_for_size, minimum_width),
									     &min_size, &nat_size);
	      pop_recursion_check (widget, orientation);
            }
        }

      if (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));
        }

      adjusted_min     = min_size;
      adjusted_natural = nat_size;
      GTK_WIDGET_GET_CLASS (widget)->adjust_size_request (widget,
                                                          orientation,
                                                          &adjusted_min,
                                                          &adjusted_natural);

      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_ORIENTATION_VERTICAL ? "vertical" : "horizontal",
                     adjusted_min, adjusted_natural,
                     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_ORIENTATION_VERTICAL ? "vertical" : "horizontal",
                     adjusted_min, adjusted_natural,
                     min_size, nat_size);
          /* don't use the adjustment */
        }
      else
        {
          /* adjustment looks good */
          min_size = adjusted_min;
          nat_size = adjusted_natural;
        }

      _gtk_size_request_cache_commit (cache,
                                      orientation,
                                      for_size,
                                      min_size,
                                      nat_size);
    }

  if (minimum_size)
    *minimum_size = min_size;

  if (natural_size)
    *natural_size = nat_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_ORIENTATION_HORIZONTAL ?
                     "width for height" : "height for width" ,
                     for_size, min_size, nat_size,
                     found_in_cache ? "yes" : "no"));
}
Пример #6
0
static void
commit_cached_size (GtkWidget         *widget,
		    GtkSizeGroupMode   orientation,
		    gint               for_size,
		    gint               minimum_size,
		    gint               natural_size)
{
  SizeRequestCache  *cache;
  SizeRequest      **cached_sizes;
  guint              i, n_sizes;

  cache = _gtk_widget_peek_request_cache (widget);

  /* First handle caching of the base requests */
  if (for_size < 0)
    {
      if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
	{
	  cache->cached_width.minimum_size = minimum_size;
	  cache->cached_width.natural_size = natural_size;
	  cache->cached_base_width = TRUE;
	}
      else
	{
	  cache->cached_height.minimum_size = minimum_size;
	  cache->cached_height.natural_size = natural_size;
	  cache->cached_base_height = TRUE;
	}
      return;
    }

  /* Check if the minimum_size and natural_size is already
   * in the cache and if this result can be used to extend
   * that cache entry 
   */
  if (orientation == GTK_SIZE_GROUP_HORIZONTAL)
    {
      cached_sizes = cache->widths;
      n_sizes = cache->cached_widths;
    }
  else
    {
      cached_sizes = cache->heights;
      n_sizes = cache->cached_heights;
    }

  for (i = 0; i < n_sizes; i++)
    {
      if (cached_sizes[i]->cached_size.minimum_size == minimum_size &&
	  cached_sizes[i]->cached_size.natural_size == natural_size)
	{
	  cached_sizes[i]->lower_for_size = MIN (cached_sizes[i]->lower_for_size, for_size);
	  cached_sizes[i]->upper_for_size = MAX (cached_sizes[i]->upper_for_size, for_size);
	  return;
	}
    }

  /* 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->cached_widths < GTK_SIZE_REQUEST_CACHED_SIZES)
	{
	  cache->cached_widths++;
	  cache->last_cached_width = cache->cached_widths - 1;
	}
      else
	{
	  if (++cache->last_cached_width == GTK_SIZE_REQUEST_CACHED_SIZES)
	    cache->last_cached_width = 0;
	}

      if (!cache->widths)
	cache->widths = g_slice_alloc0 (sizeof (SizeRequest *) * GTK_SIZE_REQUEST_CACHED_SIZES);

      if (!cache->widths[cache->last_cached_width])
	cache->widths[cache->last_cached_width] = g_slice_new (SizeRequest);

      cache->widths[cache->last_cached_width]->lower_for_size = for_size;
      cache->widths[cache->last_cached_width]->upper_for_size = for_size;
      cache->widths[cache->last_cached_width]->cached_size.minimum_size = minimum_size;
      cache->widths[cache->last_cached_width]->cached_size.natural_size = natural_size;
    }
  else /* GTK_SIZE_GROUP_VERTICAL */
    {
      if (cache->cached_heights < GTK_SIZE_REQUEST_CACHED_SIZES)
	{
	  cache->cached_heights++;
	  cache->last_cached_height = cache->cached_heights - 1;
	}
      else
	{
	  if (++cache->last_cached_height == GTK_SIZE_REQUEST_CACHED_SIZES)
	    cache->last_cached_height = 0;
	}

      if (!cache->heights)
	cache->heights = g_slice_alloc0 (sizeof (SizeRequest *) * GTK_SIZE_REQUEST_CACHED_SIZES);

      if (!cache->heights[cache->last_cached_height])
	cache->heights[cache->last_cached_height] = g_slice_new (SizeRequest);

      cache->heights[cache->last_cached_height]->lower_for_size = for_size;
      cache->heights[cache->last_cached_height]->upper_for_size = for_size;
      cache->heights[cache->last_cached_height]->cached_size.minimum_size = minimum_size;
      cache->heights[cache->last_cached_height]->cached_size.natural_size = natural_size;
    }
}