Commit 316d4504 authored by Alexander Larsson's avatar Alexander Larsson

Handle non-baseline supporting subclasses overriding baseline supporting classes

If a subclass (say a child of GtkButton) overrides the non-baseline
size request methods we need to call these, rather than the new
get_height_and_baseline_for_width method.

In order to handle this we make the default for this method to be
NULL, and instead check at runtime which method to call. If any
non-baseline vfunc has changed in a class but the baseline one
hasn't, then we can't use the baseline one.
parent c7b4dd5f
......@@ -93,6 +93,46 @@ get_vfunc_name (GtkOrientation orientation,
return for_size < 0 ? "get_preferred_height" : "get_preferred_height_for_width";
}
static gboolean
widget_class_has_baseline_support (GtkWidgetClass *widget_class)
{
GtkWidgetClass *parent_class;
if (widget_class->get_preferred_height_and_baseline_for_width == NULL)
return FALSE;
/* This is kinda hacky, but for backwards compatibility reasons we have to handle the case
where a class previously did not support get_preferred_height_and_baseline_for_width,
but then gained support for it, and a subclass of it overrides the previous non-baseline
methods. If this happens we need to call the overridden (non-baseline supporting) versions
on the subclass, rather than the inherited but not overriddent new get_preferred_height_and_baseline_for_width.
*/
/* Loop over all parent classes that inherit the same get_preferred_height_and_baseline_for_width */
parent_class = g_type_class_peek_parent (widget_class);
while (parent_class != NULL &&
parent_class->get_preferred_height_and_baseline_for_width == widget_class->get_preferred_height_and_baseline_for_width)
{
if (parent_class->get_preferred_height != widget_class->get_preferred_height ||
parent_class->get_preferred_height_for_width != widget_class->get_preferred_height_for_width)
return FALSE;
parent_class = g_type_class_peek_parent (parent_class);
}
return TRUE;
}
gboolean
_gtk_widget_has_baseline_support (GtkWidget *widget)
{
GtkWidgetClass *widget_class;
widget_class = GTK_WIDGET_GET_CLASS (widget);
return widget_class_has_baseline_support (widget_class);
}
static void
gtk_widget_query_size_for_orientation (GtkWidget *widget,
GtkOrientation orientation,
......@@ -170,9 +210,12 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
if (for_size < 0)
{
push_recursion_check (widget, orientation, for_size);
widget_class->get_preferred_height_and_baseline_for_width (widget, -1,
&min_size, &nat_size,
&min_baseline, &nat_baseline);
if (widget_class_has_baseline_support (widget_class))
widget_class->get_preferred_height_and_baseline_for_width (widget, -1,
&min_size, &nat_size,
&min_baseline, &nat_baseline);
else
widget_class->get_preferred_height (widget, &min_size, &nat_size);
pop_recursion_check (widget, orientation);
}
else
......@@ -194,9 +237,13 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
&adjusted_for_size);
push_recursion_check (widget, orientation, for_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);
if (widget_class_has_baseline_support (widget_class))
widget_class->get_preferred_height_and_baseline_for_width (widget, MAX (adjusted_for_size, minimum_width),
&min_size, &nat_size,
&min_baseline, &nat_baseline);
else
widget_class->get_preferred_height_for_width (widget, MAX (adjusted_for_size, minimum_width),
&min_size, &nat_size);
pop_recursion_check (widget, orientation);
}
}
......
......@@ -799,12 +799,6 @@ 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);
......@@ -1124,7 +1118,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->get_preferred_height_and_baseline_for_width = NULL;
klass->state_changed = NULL;
klass->state_flags_changed = gtk_widget_real_state_flags_changed;
klass->parent_set = NULL;
......@@ -5417,7 +5411,8 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
/* 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)
(gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE ||
!_gtk_widget_has_baseline_support (widget)))
baseline = -1;
alloc_needed = priv->alloc_needed;
......@@ -13619,25 +13614,6 @@ 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
......
......@@ -77,6 +77,7 @@ void _gtk_widget_get_preferred_size_for_size (GtkWidget *widget,
gint size,
gint *minimum,
gint *natural);
gboolean _gtk_widget_has_baseline_support (GtkWidget *widget);
gboolean _gtk_widget_get_translation_to_window (GtkWidget *widget,
GdkWindow *window,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment