widget: Fix gtk_widget_size_allocate()

Compute the matrix for adjusted sizes etc properly.
This commit is contained in:
Benjamin Otte 2019-02-19 05:50:49 +01:00
parent 36ac867ea9
commit d247e5707d
3 changed files with 63 additions and 107 deletions

View File

@ -208,6 +208,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
int adjusted_for_size; int adjusted_for_size;
int minimum_for_size = 0; int minimum_for_size = 0;
int natural_for_size = 0; int natural_for_size = 0;
int dummy = 0;
/* Pull the minimum for_size from the cache as it's needed to adjust /* Pull the minimum for_size from the cache as it's needed to adjust
* the proposed 'for_size' */ * the proposed 'for_size' */
@ -221,7 +222,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
adjusted_for_size = for_size; adjusted_for_size = for_size;
gtk_widget_adjust_size_allocation (widget, OPPOSITE_ORIENTATION (orientation), gtk_widget_adjust_size_allocation (widget, OPPOSITE_ORIENTATION (orientation),
&for_size, &natural_for_size, &for_size, &natural_for_size,
NULL, &adjusted_for_size); &dummy, &adjusted_for_size);
adjusted_for_size -= css_extra_for_size; adjusted_for_size -= css_extra_for_size;

View File

@ -4188,11 +4188,7 @@ gtk_widget_allocate (GtkWidget *widget,
const graphene_matrix_t *transform) const graphene_matrix_t *transform)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
int real_width; GdkRectangle adjusted;
int real_height;
int adjusted_width;
int adjusted_height;
graphene_matrix_t adjusted_transform;
gboolean alloc_needed; gboolean alloc_needed;
gboolean size_changed; gboolean size_changed;
gboolean baseline_changed; gboolean baseline_changed;
@ -4249,9 +4245,7 @@ gtk_widget_allocate (GtkWidget *widget,
priv->allocated_height = height; priv->allocated_height = height;
priv->allocated_size_baseline = baseline; priv->allocated_size_baseline = baseline;
adjusted_width = width; adjusted = (GdkRectangle) { 0, 0, width, height };
adjusted_height = height;
graphene_matrix_init_from_matrix (&adjusted_transform, transform);
if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
{ {
/* Go ahead and request the height for allocated width, note that the internals /* Go ahead and request the height for allocated width, note that the internals
@ -4291,47 +4285,52 @@ gtk_widget_allocate (GtkWidget *widget,
GTK_ORIENTATION_HORIZONTAL, GTK_ORIENTATION_HORIZONTAL,
&dummy, &dummy,
&natural_width, &natural_width,
&adjusted_transform, &adjusted.x,
&adjusted_width); &adjusted.width);
gtk_widget_adjust_size_allocation (widget, gtk_widget_adjust_size_allocation (widget,
GTK_ORIENTATION_VERTICAL, GTK_ORIENTATION_VERTICAL,
&dummy, &dummy,
&natural_height, &natural_height,
&adjusted_transform, &adjusted.y,
&adjusted_height); &adjusted.height);
if (baseline >= 0) if (baseline >= 0)
baseline -= priv->margin.top; baseline -= priv->margin.top;
real_width = adjusted_width; if (adjusted.width < 0 || adjusted.height < 0)
real_height = adjusted_height;
if (real_width < 0 || real_height < 0)
{ {
g_warning ("gtk_widget_size_allocate(): attempt to allocate %s %s %p with width %d and height %d", g_warning ("gtk_widget_size_allocate(): attempt to allocate %s %s %p with width %d and height %d",
G_OBJECT_TYPE_NAME (widget), gtk_css_node_get_name (priv->cssnode), widget, G_OBJECT_TYPE_NAME (widget), gtk_css_node_get_name (priv->cssnode), widget,
real_width, adjusted.width,
real_height); adjusted.height);
real_width = 0; adjusted.width = 0;
real_height = 0; adjusted.height = 0;
} }
if (G_UNLIKELY (_gtk_widget_get_has_surface (widget))) if (G_UNLIKELY (_gtk_widget_get_has_surface (widget)))
{ {
real_width = MAX (1, real_width); adjusted.width = MAX (1, adjusted.width);
real_height = MAX (1, real_height); adjusted.height = MAX (1, adjusted.height);
} }
style = gtk_css_node_get_style (priv->cssnode); style = gtk_css_node_get_style (priv->cssnode);
get_box_margin (style, &margin); get_box_margin (style, &margin);
get_box_border (style, &border); get_box_border (style, &border);
get_box_padding (style, &padding); get_box_padding (style, &padding);
graphene_matrix_translate (&adjusted_transform, adjusted.x += margin.left + border.left + padding.left;
&GRAPHENE_POINT3D_INIT ( adjusted.y += margin.top + border.top + padding.top;
margin.left + border.left + padding.left,
margin.top + border.top + padding.top, /* Since gtk_widget_measure does it for us, we can be sure here that
0 * the given alloaction is large enough for the css margin/bordder/padding */
)); adjusted.width -= margin.left + border.left + padding.left +
margin.right + border.right + padding.right;
adjusted.height -= margin.top + border.top + padding.top +
margin.bottom + border.bottom + padding.bottom;
if (baseline >= 0)
baseline -= margin.top + border.top + padding.top;
graphene_matrix_init_translate (&priv->transform, &GRAPHENE_POINT3D_INIT (adjusted.x, adjusted.y, 0));
graphene_matrix_multiply (&priv->transform, transform, &priv->transform);
if (!alloc_needed && !size_changed && !baseline_changed) if (!alloc_needed && !size_changed && !baseline_changed)
{ {
@ -4347,20 +4346,11 @@ gtk_widget_allocate (GtkWidget *widget,
window_alloc.width, window_alloc.height); window_alloc.width, window_alloc.height);
} }
goto only_transform_changed; goto skip_allocate;
} }
/* Since gtk_widget_measure does it for us, we can be sure here that priv->width = adjusted.width;
* the given alloaction is large enough for the css margin/bordder/padding */ priv->height = adjusted.height;
real_width -= margin.left + border.left + padding.left +
margin.right + border.right + padding.right;
real_height -= margin.top + border.top + padding.top +
margin.bottom + border.bottom + padding.bottom;
if (baseline >= 0)
baseline -= margin.top + border.top + padding.top;
priv->width = real_width;
priv->height = real_height;
priv->baseline = baseline; priv->baseline = baseline;
if (g_signal_has_handler_pending (widget, widget_signals[SIZE_ALLOCATE], 0, FALSE)) if (g_signal_has_handler_pending (widget, widget_signals[SIZE_ALLOCATE], 0, FALSE))
@ -4389,9 +4379,7 @@ gtk_widget_allocate (GtkWidget *widget,
gtk_widget_update_paintables (widget); gtk_widget_update_paintables (widget);
only_transform_changed: skip_allocate:
graphene_matrix_init_from_matrix (&priv->transform, &adjusted_transform);
if (size_changed || baseline_changed) if (size_changed || baseline_changed)
gtk_widget_queue_draw (widget); gtk_widget_queue_draw (widget);
else if (transform_changed && priv->parent) else if (transform_changed && priv->parent)
@ -4616,11 +4604,10 @@ effective_align (GtkAlign align,
} }
static void static void
adjust_for_align (GtkOrientation orientation, adjust_for_align (GtkAlign align,
GtkAlign align, gint *natural_size,
int *natural_size, gint *allocated_pos,
graphene_matrix_t *transform, gint *allocated_size)
int *allocated_size)
{ {
switch (align) switch (align)
{ {
@ -4630,38 +4617,20 @@ adjust_for_align (GtkOrientation orientation,
/* change nothing */ /* change nothing */
break; break;
case GTK_ALIGN_START: case GTK_ALIGN_START:
/* keep position where it is */ /* keep *allocated_pos where it is */
*allocated_size = MIN (*allocated_size, *natural_size); *allocated_size = MIN (*allocated_size, *natural_size);
break; break;
case GTK_ALIGN_END: case GTK_ALIGN_END:
if (*allocated_size > *natural_size) if (*allocated_size > *natural_size)
{ {
if (transform) *allocated_pos += (*allocated_size - *natural_size);
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
graphene_matrix_translate (transform,
&GRAPHENE_POINT3D_INIT (*allocated_size - *natural_size, 0, 0));
else
graphene_matrix_translate (transform,
&GRAPHENE_POINT3D_INIT (0, *allocated_size - *natural_size, 0));
}
*allocated_size = *natural_size; *allocated_size = *natural_size;
} }
break; break;
case GTK_ALIGN_CENTER: case GTK_ALIGN_CENTER:
if (*allocated_size > *natural_size) if (*allocated_size > *natural_size)
{ {
if (transform) *allocated_pos += (*allocated_size - *natural_size) / 2;
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
graphene_matrix_translate (transform,
&GRAPHENE_POINT3D_INIT ((*allocated_size - *natural_size) / 2, 0, 0));
else
graphene_matrix_translate (transform,
&GRAPHENE_POINT3D_INIT (0, (*allocated_size - *natural_size) / 2, 0));
}
*allocated_size = MIN (*allocated_size, *natural_size); *allocated_size = MIN (*allocated_size, *natural_size);
} }
break; break;
@ -4669,27 +4638,17 @@ adjust_for_align (GtkOrientation orientation,
} }
static void static void
adjust_for_margin (GtkOrientation orientation, adjust_for_margin(gint start_margin,
int start_margin, gint end_margin,
int end_margin, gint *minimum_size,
int *minimum_size, gint *natural_size,
int *natural_size, gint *allocated_pos,
graphene_matrix_t *transform, gint *allocated_size)
int *allocated_size)
{ {
*minimum_size -= (start_margin + end_margin); *minimum_size -= (start_margin + end_margin);
*natural_size -= (start_margin + end_margin); *natural_size -= (start_margin + end_margin);
*allocated_pos += start_margin;
*allocated_size -= (start_margin + end_margin); *allocated_size -= (start_margin + end_margin);
if (transform)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
graphene_matrix_translate (transform,
&GRAPHENE_POINT3D_INIT (start_margin, 0, 0));
else
graphene_matrix_translate (transform,
&GRAPHENE_POINT3D_INIT (0, start_margin, 0));
}
} }
void void
@ -4697,32 +4656,28 @@ gtk_widget_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size, gint *natural_size,
graphene_matrix_t *transform, gint *allocated_pos,
gint *allocated_size) gint *allocated_size)
{ {
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
if (orientation == GTK_ORIENTATION_HORIZONTAL) if (orientation == GTK_ORIENTATION_HORIZONTAL)
{ {
adjust_for_margin (orientation, adjust_for_margin (priv->margin.left,
priv->margin.left,
priv->margin.right, priv->margin.right,
minimum_size, natural_size, minimum_size, natural_size,
transform, allocated_size); allocated_pos, allocated_size);
adjust_for_align (orientation, adjust_for_align (effective_align (priv->halign, _gtk_widget_get_direction (widget)),
effective_align (priv->halign, _gtk_widget_get_direction (widget)), natural_size, allocated_pos, allocated_size);
natural_size, transform, allocated_size);
} }
else else
{ {
adjust_for_margin (orientation, adjust_for_margin (priv->margin.top,
priv->margin.top,
priv->margin.bottom, priv->margin.bottom,
minimum_size, natural_size, minimum_size, natural_size,
transform, allocated_size); allocated_pos, allocated_size);
adjust_for_align (orientation, adjust_for_align (effective_align (priv->valign, GTK_TEXT_DIR_NONE),
effective_align (priv->valign, GTK_TEXT_DIR_NONE), natural_size, allocated_pos, allocated_size);
natural_size, transform, allocated_size);
} }
} }

View File

@ -304,7 +304,7 @@ void gtk_widget_adjust_size_allocation (GtkWidget *w
GtkOrientation orientation, GtkOrientation orientation,
gint *minimum_size, gint *minimum_size,
gint *natural_size, gint *natural_size,
graphene_matrix_t *transform, gint *allocated_pos,
gint *allocated_size); gint *allocated_size);
void gtk_widget_adjust_baseline_request (GtkWidget *widget, void gtk_widget_adjust_baseline_request (GtkWidget *widget,
gint *minimum_baseline, gint *minimum_baseline,