[gtk+/wip/baseline: 2/7] Initial support for baselines
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/baseline: 2/7] Initial support for baselines
- Date: Thu, 7 Mar 2013 19:25:26 +0000 (UTC)
commit d8a65ae30487ebe7359fb0575651c61fef7ddeb5
Author: Alexander Larsson <alexl redhat com>
Date: Tue Mar 5 14:54:03 2013 +0100
Initial support for baselines
This modifies the size machinery in order to allow baseline support.
We add a new widget vfunc get_preferred_height_and_baseline_for_width which
queries the normal height_for_width (or non-for-width if width is -1) and
additionally returns optional (-1 means "no baseline") baselines for the minimal
and natural heights.
We also add a new gtk_widget_size_allocate_with_baseline() which baseline-aware
containers can use to allocate children with a specific baseline, either one inherited
from the parent, or one introduced due to requested baseline alignment in the
container itself. size_allocate_with_baseline() works just like a normal size
allocation, except the baseline gets recorded so that the child can access it
via gtk_widget_get_allocated_baseline() when it aligns itself.
There are also adjust_baseline_request/allocation similar to the allocation
adjustment, and we extend the size request cache to also store the baselines.
gtk/gtkcontainer.c | 50 +++++++++++
gtk/gtksizerequest.c | 166 +++++++++++++++++++++++++++++---------
gtk/gtksizerequestcache.c | 18 ++++-
gtk/gtksizerequestcacheprivate.h | 10 ++-
gtk/gtkwidget.c | 140 +++++++++++++++++++++++++++-----
gtk/gtkwidget.h | 25 +++++-
gtk/gtkwidgetprivate.h | 4 +-
7 files changed, 348 insertions(+), 65 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index ce16fe4..09bfffa 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -309,12 +309,17 @@ static void gtk_container_adjust_size_request (GtkWidget *widget,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size);
+static void gtk_container_adjust_baseline_request (GtkWidget *widget,
+ gint *minimum_baseline,
+ gint *natural_baseline);
static void gtk_container_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size,
gint *allocated_pos,
gint *allocated_size);
+static void gtk_container_adjust_baseline_allocation (GtkWidget *widget,
+ gint *baseline);
static GtkSizeRequestMode gtk_container_get_request_mode (GtkWidget *widget);
static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
@@ -444,7 +449,9 @@ gtk_container_class_init (GtkContainerClass *class)
widget_class->focus = gtk_container_focus;
widget_class->adjust_size_request = gtk_container_adjust_size_request;
+ widget_class->adjust_baseline_request = gtk_container_adjust_baseline_request;
widget_class->adjust_size_allocation = gtk_container_adjust_size_allocation;
+ widget_class->adjust_baseline_allocation = gtk_container_adjust_baseline_allocation;
widget_class->get_request_mode = gtk_container_get_request_mode;
class->add = gtk_container_add_unimplemented;
@@ -1918,6 +1925,28 @@ gtk_container_adjust_size_request (GtkWidget *widget,
}
static void
+gtk_container_adjust_baseline_request (GtkWidget *widget,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GtkContainer *container;
+
+ container = GTK_CONTAINER (widget);
+
+ if (GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
+ {
+ int border_width;
+
+ border_width = container->priv->border_width;
+
+ *minimum_baseline += border_width;
+ *natural_baseline += border_width;
+ }
+
+ parent_class->adjust_baseline_request (widget, minimum_baseline, natural_baseline);
+}
+
+static void
gtk_container_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation,
gint *minimum_size,
@@ -1952,6 +1981,27 @@ gtk_container_adjust_size_allocation (GtkWidget *widget,
allocated_size);
}
+static void
+gtk_container_adjust_baseline_allocation (GtkWidget *widget,
+ gint *baseline)
+{
+ GtkContainer *container;
+ int border_width;
+
+ container = GTK_CONTAINER (widget);
+
+ if (GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
+ {
+ border_width = container->priv->border_width;
+
+ if (*baseline >= 0)
+ *baseline -= border_width;
+ }
+
+ parent_class->adjust_baseline_allocation (widget, baseline);
+}
+
+
typedef struct {
gint hfw;
gint wfh;
diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c
index 0ce86bd..dfc776c 100644
--- a/gtk/gtksizerequest.c
+++ b/gtk/gtksizerequest.c
@@ -98,11 +98,16 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
GtkOrientation orientation,
gint for_size,
gint *minimum_size,
- gint *natural_size)
+ gint *natural_size,
+ gint *minimum_baseline,
+ gint *natural_baseline)
{
SizeRequestCache *cache;
+ GtkWidgetClass *widget_class;
gint min_size = 0;
gint nat_size = 0;
+ gint min_baseline = -1;
+ gint nat_baseline = -1;
gboolean found_in_cache;
if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE)
@@ -113,7 +118,11 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
orientation,
for_size,
&min_size,
- &nat_size);
+ &nat_size,
+ &min_baseline,
+ &nat_baseline);
+
+ widget_class = GTK_WIDGET_GET_CLASS (widget);
if (!found_in_cache)
{
@@ -126,7 +135,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
if (for_size < 0)
{
push_recursion_check (widget, orientation, for_size);
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, &min_size, &nat_size);
+ widget_class->get_preferred_width (widget, &min_size, &nat_size);
pop_recursion_check (widget, orientation);
}
else
@@ -140,17 +149,17 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
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);
+ widget_class->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);
+ widget_class->get_preferred_width_for_height (widget,
+ MAX (adjusted_for_size, minimum_height),
+ &min_size, &nat_size);
pop_recursion_check (widget, orientation);
}
}
@@ -159,7 +168,9 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
if (for_size < 0)
{
push_recursion_check (widget, orientation, for_size);
- GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, &min_size, &nat_size);
+ widget_class->get_preferred_height_and_baseline_for_width (widget, -1,
+ &min_size, &nat_size,
+ &min_baseline, &nat_baseline);
pop_recursion_check (widget, orientation);
}
else
@@ -173,17 +184,17 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
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);
+ widget_class->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);
+ widget_class->get_preferred_height_and_baseline_for_width (widget, MAX (adjusted_for_size,
minimum_width),
+ &min_size, &nat_size,
+ &min_baseline, &nat_baseline);
pop_recursion_check (widget, orientation);
}
}
@@ -196,10 +207,10 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
adjusted_min = min_size;
adjusted_natural = nat_size;
- GTK_WIDGET_GET_CLASS (widget)->adjust_size_request (widget,
- orientation,
- &adjusted_min,
- &adjusted_natural);
+ widget_class->adjust_size_request (widget,
+ orientation,
+ &adjusted_min,
+ &adjusted_natural);
if (adjusted_min < min_size ||
adjusted_natural < nat_size)
@@ -227,11 +238,42 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
nat_size = adjusted_natural;
}
+ if (min_baseline != -1 || nat_baseline != -1)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ g_warning ("%s %p reported a horizontal baseline",
+ G_OBJECT_TYPE_NAME (widget), widget);
+ min_baseline = -1;
+ nat_baseline = -1;
+ }
+ else if (min_baseline == -1 || nat_baseline == -1)
+ {
+ g_warning ("%s %p reported baseline for only one of min/natural (min: %d, natural: %d)",
+ G_OBJECT_TYPE_NAME (widget), widget,
+ min_baseline, nat_baseline);
+ min_baseline = -1;
+ nat_baseline = -1;
+ }
+ else if (gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE)
+ {
+ /* Ignore requested baseline for non-aligned widgets */
+ min_baseline = -1;
+ nat_baseline = -1;
+ }
+ else
+ widget_class->adjust_baseline_request (widget,
+ &min_baseline,
+ &nat_baseline);
+ }
+
_gtk_size_request_cache_commit (cache,
orientation,
for_size,
min_size,
- nat_size);
+ nat_size,
+ min_baseline,
+ nat_baseline);
}
if (minimum_size)
@@ -240,15 +282,26 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
if (natural_size)
*natural_size = nat_size;
+ if (minimum_baseline)
+ *minimum_baseline = min_baseline;
+
+ if (natural_baseline)
+ *natural_baseline = nat_baseline;
+
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",
+ g_print ("[%p] %s\t%s: %d is minimum %d and natural: %d",
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"));
+ for_size, min_size, nat_size);
+ if (min_baseline != -1 || nat_baseline != -1)
+ g_print (", baseline %d/%d",
+ min_baseline, nat_baseline);
+ g_print (" (hit cache: %s)\n",
+ found_in_cache ? "yes" : "no")
+ );
}
/* This is the main function that checks for a cached size and
@@ -261,7 +314,9 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
GtkOrientation orientation,
gint for_size,
gint *minimum,
- gint *natural)
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
{
GHashTable *widgets;
GHashTableIter iter;
@@ -274,12 +329,17 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
*minimum = 0;
if (natural)
*natural = 0;
+ if (minimum_baseline)
+ *minimum_baseline = -1;
+ if (natural_baseline)
+ *natural_baseline = -1;
return;
}
if (G_LIKELY (!_gtk_widget_get_sizegroups (widget)))
{
- gtk_widget_query_size_for_orientation (widget, orientation, for_size, minimum, natural);
+ gtk_widget_query_size_for_orientation (widget, orientation, for_size, minimum, natural,
+ minimum_baseline, natural_baseline);
return;
}
@@ -293,7 +353,7 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
GtkWidget *tmp_widget = key;
gint min_dimension, nat_dimension;
- gtk_widget_query_size_for_orientation (tmp_widget, orientation, for_size, &min_dimension,
&nat_dimension);
+ gtk_widget_query_size_for_orientation (tmp_widget, orientation, for_size, &min_dimension,
&nat_dimension, NULL, NULL);
min_result = MAX (min_result, min_dimension);
nat_result = MAX (nat_result, nat_dimension);
@@ -303,6 +363,13 @@ _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
g_hash_table_destroy (widgets);
+ /* Baselines make no sense with sizegroups really */
+ if (minimum_baseline)
+ *minimum_baseline = -1;
+
+ if (natural_baseline)
+ *natural_baseline = -1;
+
if (minimum)
*minimum = min_result;
@@ -375,7 +442,8 @@ gtk_widget_get_preferred_width (GtkWidget *widget,
GTK_ORIENTATION_HORIZONTAL,
-1,
minimum_width,
- natural_width);
+ natural_width,
+ NULL, NULL);
}
@@ -409,7 +477,8 @@ gtk_widget_get_preferred_height (GtkWidget *widget,
GTK_ORIENTATION_VERTICAL,
-1,
minimum_height,
- natural_height);
+ natural_height,
+ NULL, NULL);
}
@@ -446,7 +515,8 @@ gtk_widget_get_preferred_width_for_height (GtkWidget *widget,
GTK_ORIENTATION_HORIZONTAL,
height,
minimum_width,
- natural_width);
+ natural_width,
+ NULL, NULL);
}
/**
@@ -481,7 +551,29 @@ gtk_widget_get_preferred_height_for_width (GtkWidget *widget,
GTK_ORIENTATION_VERTICAL,
width,
minimum_height,
- natural_height);
+ natural_height,
+ NULL, NULL);
+}
+
+void
+gtk_widget_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (minimum_height != NULL || natural_height != NULL);
+ g_return_if_fail (width >= -1);
+
+ _gtk_widget_compute_size_for_orientation (widget,
+ GTK_ORIENTATION_VERTICAL,
+ width,
+ minimum_height,
+ natural_height,
+ minimum_baseline,
+ natural_baseline);
}
/**
diff --git a/gtk/gtksizerequestcache.c b/gtk/gtksizerequestcache.c
index 102e2dd..e6107c7 100644
--- a/gtk/gtksizerequestcache.c
+++ b/gtk/gtksizerequestcache.c
@@ -67,7 +67,9 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
GtkOrientation orientation,
gint for_size,
gint minimum_size,
- gint natural_size)
+ gint natural_size,
+ gint minimum_baseline,
+ gint natural_baseline)
{
SizeRequest **cached_sizes;
SizeRequest *cached_size;
@@ -78,6 +80,8 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
{
cache->cached_size[orientation].minimum_size = minimum_size;
cache->cached_size[orientation].natural_size = natural_size;
+ cache->cached_size[orientation].minimum_baseline = minimum_baseline;
+ cache->cached_size[orientation].natural_baseline = natural_baseline;
cache->flags[orientation].cached_size_valid = TRUE;
return;
}
@@ -92,7 +96,9 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
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]->cached_size.natural_size == natural_size &&
+ cached_sizes[i]->cached_size.minimum_baseline == minimum_baseline &&
+ cached_sizes[i]->cached_size.natural_baseline == natural_baseline)
{
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);
@@ -125,6 +131,8 @@ _gtk_size_request_cache_commit (SizeRequestCache *cache,
cached_size->upper_for_size = for_size;
cached_size->cached_size.minimum_size = minimum_size;
cached_size->cached_size.natural_size = natural_size;
+ cached_size->cached_size.minimum_baseline = minimum_baseline;
+ cached_size->cached_size.natural_baseline = natural_baseline;
}
/* looks for a cached size request for this for_size.
@@ -137,7 +145,9 @@ _gtk_size_request_cache_lookup (SizeRequestCache *cache,
GtkOrientation orientation,
gint for_size,
gint *minimum,
- gint *natural)
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
{
CachedSize *result = NULL;
@@ -168,6 +178,8 @@ _gtk_size_request_cache_lookup (SizeRequestCache *cache,
{
*minimum = result->minimum_size;
*natural = result->natural_size;
+ *minimum_baseline = result->minimum_baseline;
+ *natural_baseline = result->natural_baseline;
return TRUE;
}
else
diff --git a/gtk/gtksizerequestcacheprivate.h b/gtk/gtksizerequestcacheprivate.h
index ac851dd..e458428 100644
--- a/gtk/gtksizerequestcacheprivate.h
+++ b/gtk/gtksizerequestcacheprivate.h
@@ -41,6 +41,8 @@ G_BEGIN_DECLS
typedef struct {
gint minimum_size;
gint natural_size;
+ gint minimum_baseline;
+ gint natural_baseline;
} CachedSize;
typedef struct
@@ -72,12 +74,16 @@ void _gtk_size_request_cache_commit (SizeRequestCach
GtkOrientation orientation,
gint for_size,
gint minimum_size,
- gint natural_size);
+ gint natural_size,
+ gint minimum_baseline,
+ gint natural_baseline);
gboolean _gtk_size_request_cache_lookup (SizeRequestCache *cache,
GtkOrientation orientation,
gint for_size,
gint *minimum,
- gint *natural);
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline);
G_END_DECLS
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index f9c283e..97be88d 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -392,6 +392,7 @@ struct _GtkWidgetPrivate
/* The widget's allocated size */
GtkAllocation allocation;
+ gint allocated_baseline;
/* The widget's requested sizes */
SizeRequestCache requests;
@@ -686,6 +687,12 @@ static void gtk_widget_real_get_width (GtkWidget
static void gtk_widget_real_get_height (GtkWidget *widget,
gint *minimum_size,
gint *natural_size);
+static void gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height,
+ gint *minimum_baseline,
+ gint *natural_baseline);
static void gtk_widget_queue_tooltip_query (GtkWidget *widget);
@@ -694,12 +701,17 @@ static void gtk_widget_real_adjust_size_request (GtkWidget
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size);
+static void gtk_widget_real_adjust_baseline_request (GtkWidget *widget,
+ gint *minimum_baseline,
+ gint *natural_baseline);
static void gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation,
gint *minimum_size,
gint *natural_size,
gint *allocated_pos,
gint *allocated_size);
+static void gtk_widget_real_adjust_baseline_allocation (GtkWidget *widget,
+ gint *baseline);
static void gtk_widget_set_usize_internal (GtkWidget *widget,
gint width,
@@ -981,6 +993,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->get_preferred_height = gtk_widget_real_get_height;
klass->get_preferred_width_for_height = gtk_widget_real_get_width_for_height;
klass->get_preferred_height_for_width = gtk_widget_real_get_height_for_width;
+ klass->get_preferred_height_and_baseline_for_width =
gtk_widget_real_get_preferred_height_and_baseline_for_width;
klass->state_changed = NULL;
klass->state_flags_changed = gtk_widget_real_state_flags_changed;
klass->parent_set = NULL;
@@ -1040,7 +1053,9 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->get_accessible = gtk_widget_real_get_accessible;
klass->adjust_size_request = gtk_widget_real_adjust_size_request;
+ klass->adjust_baseline_request = gtk_widget_real_adjust_baseline_request;
klass->adjust_size_allocation = gtk_widget_real_adjust_size_allocation;
+ klass->adjust_baseline_allocation = gtk_widget_real_adjust_baseline_allocation;
g_object_class_install_property (gobject_class,
PROP_NAME,
@@ -5185,23 +5200,10 @@ gtk_widget_invalidate_widget_windows (GtkWidget *widget,
invalidate_predicate, widget);
}
-/**
- * gtk_widget_size_allocate:
- * @widget: a #GtkWidget
- * @allocation: position and size to be allocated to @widget
- *
- * This function is only used by #GtkContainer subclasses, to assign a size
- * and position to their child widgets.
- *
- * In this function, the allocation may be adjusted. It will be forced
- * to a 1x1 minimum size, and the adjust_size_allocation virtual
- * method on the child will be used to adjust the allocation. Standard
- * adjustments include removing the widget's margins, and applying the
- * widget's #GtkWidget:halign and #GtkWidget:valign properties.
- **/
void
-gtk_widget_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
+gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
+ GtkAllocation *allocation,
+ gint baseline)
{
GtkWidgetPrivate *priv;
GdkRectangle real_allocation;
@@ -5209,9 +5211,11 @@ gtk_widget_size_allocate (GtkWidget *widget,
GdkRectangle adjusted_allocation;
gboolean alloc_needed;
gboolean size_changed;
+ gboolean baseline_changed;
gboolean position_changed;
gint natural_width, natural_height, dummy;
gint min_width, min_height;
+ gint old_baseline;
priv = widget->priv;
@@ -5238,17 +5242,27 @@ gtk_widget_size_allocate (GtkWidget *widget,
}
name = g_type_name (G_OBJECT_TYPE (G_OBJECT (widget)));
- g_print ("gtk_widget_size_allocate: %*s%s %d %d\n",
+ g_print ("gtk_widget_size_allocate: %*s%s %d %d",
2 * depth, " ", name,
allocation->width, allocation->height);
+ if (baseline != -1)
+ g_print (" baseline: %d", baseline);
+ g_print ("\n");
}
#endif /* G_ENABLE_DEBUG */
+ /* Never pass a baseline to a child unless it requested it.
+ This means containers don't have to manually check for this. */
+ if (baseline != -1 &&
+ gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE)
+ baseline = -1;
+
alloc_needed = priv->alloc_needed;
/* Preserve request/allocate ordering */
priv->alloc_needed = FALSE;
old_allocation = priv->allocation;
+ old_baseline = priv->allocated_baseline;
real_allocation = *allocation;
adjusted_allocation = real_allocation;
@@ -5298,6 +5312,9 @@ gtk_widget_size_allocate (GtkWidget *widget,
&natural_height,
&adjusted_allocation.y,
&adjusted_allocation.height);
+ if (baseline >= 0)
+ GTK_WIDGET_GET_CLASS (widget)->adjust_baseline_allocation (widget,
+ &baseline);
if (adjusted_allocation.x < real_allocation.x ||
adjusted_allocation.y < real_allocation.y ||
@@ -5327,14 +5344,16 @@ gtk_widget_size_allocate (GtkWidget *widget,
real_allocation.width = MAX (real_allocation.width, 1);
real_allocation.height = MAX (real_allocation.height, 1);
+ baseline_changed = old_baseline != baseline;
size_changed = (old_allocation.width != real_allocation.width ||
old_allocation.height != real_allocation.height);
position_changed = (old_allocation.x != real_allocation.x ||
old_allocation.y != real_allocation.y);
- if (!alloc_needed && !size_changed && !position_changed)
+ if (!alloc_needed && !size_changed && !position_changed && !baseline_changed)
goto out;
+ priv->allocated_baseline = baseline;
g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0, &real_allocation);
/* Size allocation is god... after consulting god, no further requests or allocations are needed */
@@ -5368,7 +5387,7 @@ gtk_widget_size_allocate (GtkWidget *widget,
}
}
- if ((size_changed || position_changed) && priv->parent &&
+ if ((size_changed || position_changed || baseline_changed) && priv->parent &&
gtk_widget_get_realized (priv->parent) && _gtk_container_get_reallocate_redraws (GTK_CONTAINER
(priv->parent)))
{
cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->parent->priv->allocation);
@@ -5380,6 +5399,28 @@ out:
gtk_widget_pop_verify_invariants (widget);
}
+
+/**
+ * gtk_widget_size_allocate:
+ * @widget: a #GtkWidget
+ * @allocation: position and size to be allocated to @widget
+ *
+ * This function is only used by #GtkContainer subclasses, to assign a size
+ * and position to their child widgets.
+ *
+ * In this function, the allocation may be adjusted. It will be forced
+ * to a 1x1 minimum size, and the adjust_size_allocation virtual
+ * method on the child will be used to adjust the allocation. Standard
+ * adjustments include removing the widget's margins, and applying the
+ * widget's #GtkWidget:halign and #GtkWidget:valign properties.
+ **/
+void
+gtk_widget_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ gtk_widget_size_allocate_with_baseline (widget, allocation, -1);
+}
+
/**
* gtk_widget_common_ancestor:
* @widget_a: a #GtkWidget
@@ -5672,6 +5713,18 @@ gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
}
}
+static void
+gtk_widget_real_adjust_baseline_allocation (GtkWidget *widget,
+ gint *baseline)
+{
+ const GtkWidgetAuxInfo *aux_info;
+
+ aux_info = _gtk_widget_get_aux_info_or_defaults (widget);
+
+ if (baseline >= 0)
+ *baseline -= aux_info->margin.top;
+}
+
static gboolean
gtk_widget_real_can_activate_accel (GtkWidget *widget,
guint signal_id)
@@ -11013,6 +11066,28 @@ gtk_widget_real_adjust_size_request (GtkWidget *widget,
}
}
+static void
+gtk_widget_real_adjust_baseline_request (GtkWidget *widget,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ const GtkWidgetAuxInfo *aux_info;
+
+ aux_info =_gtk_widget_get_aux_info_or_defaults (widget);
+
+ if (aux_info->height >= 0)
+ {
+ /* No baseline support for explicitly set height */
+ *minimum_baseline = -1;
+ *natural_baseline = -1;
+ }
+ else
+ {
+ *minimum_baseline += aux_info->margin.top;
+ *natural_baseline += aux_info->margin.top;
+ }
+}
+
/**
* _gtk_widget_peek_request_cache:
*
@@ -13163,6 +13238,25 @@ gtk_widget_real_get_width_for_height (GtkWidget *widget,
GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
}
+static void
+gtk_widget_real_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ if (width == -1)
+ GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height);
+ else
+ GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width (widget, width, minimum_height,
natural_height);
+
+ if (minimum_baseline)
+ *minimum_baseline = -1;
+ if (natural_baseline)
+ *natural_baseline = -1;
+}
+
/**
* gtk_widget_get_halign:
* @widget: a #GtkWidget
@@ -14004,6 +14098,14 @@ gtk_widget_get_allocated_height (GtkWidget *widget)
return widget->priv->allocation.height;
}
+int
+gtk_widget_get_allocated_baseline (GtkWidget *widget)
+{
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
+
+ return widget->priv->allocated_baseline;
+}
+
/**
* gtk_widget_get_requisition:
* @widget: a #GtkWidget
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index c0ff853..6fbdecf 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -433,14 +433,23 @@ struct _GtkWidgetClass
gboolean (* touch_event) (GtkWidget *widget,
GdkEventTouch *event);
+ void (* get_preferred_height_and_baseline_for_width) (GtkWidget *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height,
+ gint *minimum_baseline,
+ gint *natural_baseline);
+ void (* adjust_baseline_request)(GtkWidget *widget,
+ gint *minimum_baseline,
+ gint *natural_baseline);
+ void (* adjust_baseline_allocation) (GtkWidget *widget,
+ gint *baseline);
+
/*< private >*/
GtkWidgetClassPrivate *priv;
/* Padding for future expansion */
- void (*_gtk_reserved2) (void);
- void (*_gtk_reserved3) (void);
- void (*_gtk_reserved4) (void);
void (*_gtk_reserved5) (void);
void (*_gtk_reserved6) (void);
void (*_gtk_reserved7) (void);
@@ -498,6 +507,9 @@ void gtk_widget_size_request (GtkWidget *widget,
GtkRequisition *requisition);
void gtk_widget_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
+void gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
+ GtkAllocation *allocation,
+ gint baseline);
GtkSizeRequestMode gtk_widget_get_request_mode (GtkWidget *widget);
void gtk_widget_get_preferred_width (GtkWidget *widget,
@@ -514,6 +526,12 @@ void gtk_widget_get_preferred_width_for_height (GtkWidget *w
gint height,
gint *minimum_width,
gint *natural_width);
+void gtk_widget_get_preferred_height_and_baseline_for_width (GtkWidget *widget,
+ gint width,
+ gint *minimum_height,
+ gint *natural_height,
+ gint *minimum_baseline,
+ gint *natural_baseline);
void gtk_widget_get_preferred_size (GtkWidget *widget,
GtkRequisition *minimum_size,
GtkRequisition *natural_size);
@@ -659,6 +677,7 @@ void gtk_widget_unregister_window (GtkWidget *widget,
int gtk_widget_get_allocated_width (GtkWidget *widget);
int gtk_widget_get_allocated_height (GtkWidget *widget);
+int gtk_widget_get_allocated_baseline (GtkWidget *widget);
void gtk_widget_get_allocation (GtkWidget *widget,
GtkAllocation *allocation);
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 4542580..37a5c51 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -69,7 +69,9 @@ void _gtk_widget_compute_size_for_orientation (GtkWidget *widget,
GtkOrientation orientation,
gint for_size,
gint *minimum_size,
- gint *natural_size);
+ gint *natural_size,
+ gint *minimum_baseline,
+ gint *natural_baseline);
gboolean _gtk_widget_get_translation_to_window (GtkWidget *widget,
GdkWindow *window,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]