summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte.benjamin@googlemail.com>2021-11-09 03:15:00 +0000
committerBenjamin Otte <otte.benjamin@googlemail.com>2021-11-09 03:15:00 +0000
commit08d48201e998a06c07c5148b37bc374bbdcb9353 (patch)
tree9b4c9cac24d703c96d384c5ac6f9be33283ab828
parent27d286eb7a6fda4da0ecb4e5de3c3307ae02d49b (diff)
parent76c46739447023368db4c3e6d008b52ff4b249e0 (diff)
downloadgtk+-08d48201e998a06c07c5148b37bc374bbdcb9353.tar.gz
Merge branch 'wip/otte/for-master' into 'master'
lots of sizing fixes See merge request GNOME/gtk!4131
-rw-r--r--demos/widget-factory/widget-factory.ui2
-rw-r--r--gtk/gtkboxlayout.c268
-rw-r--r--gtk/gtklabel.c11
-rw-r--r--gtk/gtksizerequest.c3
-rw-r--r--testsuite/reftests/label-huge-max-width-chars.ref.ui11
-rw-r--r--testsuite/reftests/label-huge-max-width-chars.ui12
-rw-r--r--testsuite/reftests/label-small-max-width-chars.ref.ui11
-rw-r--r--testsuite/reftests/label-small-max-width-chars.ui12
-rw-r--r--testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui12
-rw-r--r--testsuite/reftests/label-wrapped-huge-max-width-chars.ui13
-rw-r--r--testsuite/reftests/meson.build8
-rw-r--r--testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui27
-rw-r--r--testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui30
13 files changed, 322 insertions, 98 deletions
diff --git a/demos/widget-factory/widget-factory.ui b/demos/widget-factory/widget-factory.ui
index 7c190d08cb..e31629d986 100644
--- a/demos/widget-factory/widget-factory.ui
+++ b/demos/widget-factory/widget-factory.ui
@@ -2923,7 +2923,7 @@ microphone-sensitivity-medium-symbolic</property>
<property name="resizable">0</property>
<property name="modal">1</property>
<property name="text" translatable="1">Do something?</property>
- <property name="secondary-text" translatable="1">If you do something,
+ <property name="secondary-text" translatable="1">If you don't do something,
bad things might happen.</property>
<property name="hide-on-close">1</property>
<child type="action">
diff --git a/gtk/gtkboxlayout.c b/gtk/gtkboxlayout.c
index 20b462eb40..e79c5e202a 100644
--- a/gtk/gtkboxlayout.c
+++ b/gtk/gtkboxlayout.c
@@ -288,6 +288,64 @@ gtk_box_layout_compute_opposite_size (GtkBoxLayout *self,
*natural = largest_nat;
}
+static int
+distribute_remaining_size (GtkRequestedSize *sizes,
+ gsize n_sizes,
+ GtkOrientation orientation,
+ int available,
+ int min,
+ int max)
+{
+ int total_size = 0;
+ gsize i;
+
+ if (n_sizes == 0)
+ return available;
+
+ for (i = 0; i < n_sizes; i++)
+ {
+ gtk_widget_measure (sizes[i].data,
+ orientation,
+ min,
+ &sizes[i].minimum_size, &sizes[i].natural_size,
+ NULL, NULL);
+ total_size += sizes[i].minimum_size;
+ }
+
+ if (total_size <= available)
+ return available - total_size;
+
+ /* total_size > available happens when we last ran for values too big,
+ * rerun for the correct value min == max in that case */
+ while (min < max || total_size > available)
+ {
+ int test;
+
+ if (max == G_MAXINT)
+ test = min * 2;
+ else
+ test = (min + max) / 2;
+
+ total_size = 0;
+ for (i = 0; i < n_sizes; i++)
+ {
+ gtk_widget_measure (sizes[i].data,
+ orientation,
+ test,
+ &sizes[i].minimum_size, &sizes[i].natural_size,
+ NULL, NULL);
+ total_size += sizes[i].minimum_size;
+ }
+
+ if (total_size > available)
+ min = test + 1;
+ else
+ max = test;
+ }
+
+ return available - total_size;
+}
+
static void
gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self,
GtkWidget *widget,
@@ -305,13 +363,12 @@ gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self,
int computed_minimum_below = 0, computed_natural_below = 0;
int computed_minimum_baseline = -1, computed_natural_baseline = -1;
GtkRequestedSize *sizes;
- int extra_space, size_given_to_child, i;
- int children_minimum_size = 0;
+ int available, size_given_to_child, i;
int child_size, child_minimum, child_natural;
int child_minimum_baseline, child_natural_baseline;
int n_extra_widgets = 0;
int spacing;
- gboolean have_baseline;
+ gboolean have_baseline = FALSE;
count_expand_children (widget, self->orientation, &nvis_children, &nexpand_children);
@@ -320,96 +377,132 @@ gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self,
spacing = get_spacing (self, gtk_widget_get_css_node (widget));
sizes = g_newa (GtkRequestedSize, nvis_children);
- extra_space = MAX (0, for_size - (nvis_children - 1) * spacing);
+ g_assert ((nvis_children - 1) * spacing <= for_size);
+ available = for_size - (nvis_children - 1) * spacing;
- /* Retrieve desired size for visible children */
- for (i = 0, child = _gtk_widget_get_first_child (widget);
- child != NULL;
- child = _gtk_widget_get_next_sibling (child))
+ if (self->homogeneous)
{
- int min_opposite, nat_for_min;
-
- if (!gtk_widget_should_layout (child))
- continue;
+ size_given_to_child = available / nvis_children;
+ n_extra_widgets = available % nvis_children;
- gtk_widget_measure (child,
- self->orientation,
- -1,
- &sizes[i].minimum_size, &sizes[i].natural_size,
- NULL, NULL);
- /* Don't just use the natural size as the max size,
- * the natural size is the ideal size, not necessarily
- * the maximum size.
- * Also check the nat size for opposite min size.
- */
- gtk_widget_measure (child,
- OPPOSITE_ORIENTATION (self->orientation),
- -1,
- &min_opposite, NULL,
- NULL, NULL);
- gtk_widget_measure (child,
- self->orientation,
- min_opposite,
- NULL, &nat_for_min,
- NULL, NULL);
- sizes[i].natural_size = MAX (sizes[i].natural_size, nat_for_min);
+ for (child = _gtk_widget_get_first_child (widget);
+ child != NULL;
+ child = _gtk_widget_get_next_sibling (child))
+ {
+ if (!gtk_widget_should_layout (child))
+ continue;
- children_minimum_size += sizes[i].minimum_size;
- i += 1;
- }
+ child_size = size_given_to_child;
+ if (n_extra_widgets)
+ {
+ child_size++;
+ n_extra_widgets--;
+ }
- if (self->homogeneous)
- {
- /* We still need to run the above loop to populate the minimum sizes for
- * children that aren't going to fill.
- */
+ child_minimum_baseline = child_natural_baseline = -1;
+ /* Assign the child's position. */
+ gtk_widget_measure (child,
+ OPPOSITE_ORIENTATION (self->orientation),
+ child_size,
+ &child_minimum, &child_natural,
+ &child_minimum_baseline, &child_natural_baseline);
- size_given_to_child = extra_space / nvis_children;
- n_extra_widgets = extra_space % nvis_children;
+ if (child_minimum_baseline >= 0)
+ {
+ have_baseline = TRUE;
+ computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline);
+ computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline);
+ computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline);
+ computed_natural_above = MAX (computed_natural_above, child_natural_baseline);
+ }
+ else
+ {
+ computed_minimum = MAX (computed_minimum, child_minimum);
+ computed_natural = MAX (computed_natural, child_natural);
+ }
+ }
}
else
{
+ int min_size = 0, child_min_size;
+ int n_inconstant = 0;
+
+ /* Retrieve desired size for visible children */
+ for (i = 0, child = _gtk_widget_get_first_child (widget);
+ child != NULL;
+ child = _gtk_widget_get_next_sibling (child))
+ {
+ if (!gtk_widget_should_layout (child))
+ continue;
+
+ if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_CONSTANT_SIZE)
+ {
+ gtk_widget_measure (child,
+ self->orientation,
+ -1,
+ &sizes[i].minimum_size, &sizes[i].natural_size,
+ NULL, NULL);
+ sizes[i].data = child;
+ g_assert (available >= sizes[i].minimum_size);
+ available -= sizes[i].minimum_size;
+ i++;
+ }
+ else
+ {
+ gtk_widget_measure (child,
+ OPPOSITE_ORIENTATION (self->orientation),
+ -1,
+ &child_min_size, NULL,
+ NULL, NULL);
+ min_size = MAX (min_size, child_min_size);
+ n_inconstant++;
+ sizes[nvis_children - n_inconstant].data = child;
+ }
+ }
+
+ available = distribute_remaining_size (sizes + nvis_children - n_inconstant,
+ n_inconstant,
+ self->orientation,
+ available,
+ min_size,
+ G_MAXINT);
+
/* Bring children up to size first */
- extra_space -= children_minimum_size;
- extra_space = MAX (0, extra_space);
- extra_space = gtk_distribute_natural_allocation (extra_space, nvis_children, sizes);
+ available = gtk_distribute_natural_allocation (available, nvis_children, sizes);
/* Calculate space which hasn't distributed yet,
* and is available for expanding children.
*/
if (nexpand_children > 0)
{
- size_given_to_child = extra_space / nexpand_children;
- n_extra_widgets = extra_space % nexpand_children;
+ size_given_to_child = available / nexpand_children;
+ n_extra_widgets = available % nexpand_children;
}
else
{
size_given_to_child = 0;
}
- }
-
- have_baseline = FALSE;
- for (i = 0, child = _gtk_widget_get_first_child (widget);
- child != NULL;
- child = _gtk_widget_get_next_sibling (child))
- {
- if (!gtk_widget_should_layout (child))
- continue;
- /* Assign the child's size. */
- if (self->homogeneous)
+ i = 0;
+ n_inconstant = 0;
+ for (child = _gtk_widget_get_first_child (widget);
+ child != NULL;
+ child = _gtk_widget_get_next_sibling (child))
{
- child_size = size_given_to_child;
+ if (!gtk_widget_should_layout (child))
+ continue;
- if (n_extra_widgets > 0)
+ if (sizes[i].data == child)
{
- child_size++;
- n_extra_widgets--;
+ child_size = sizes[i].minimum_size;
+ i++;
+ }
+ else
+ {
+ n_inconstant++;
+ g_assert (sizes[nvis_children - n_inconstant].data == child);
+ child_size = sizes[nvis_children - n_inconstant].minimum_size;
}
- }
- else
- {
- child_size = sizes[i].minimum_size;
if (gtk_widget_compute_expand (child, self->orientation))
{
@@ -421,30 +514,29 @@ gtk_box_layout_compute_opposite_size_for_size (GtkBoxLayout *self,
n_extra_widgets--;
}
}
- }
- child_minimum_baseline = child_natural_baseline = -1;
- /* Assign the child's position. */
- gtk_widget_measure (child,
- OPPOSITE_ORIENTATION (self->orientation),
- child_size,
- &child_minimum, &child_natural,
- &child_minimum_baseline, &child_natural_baseline);
+ child_minimum_baseline = child_natural_baseline = -1;
+ /* Assign the child's position. */
+ gtk_widget_measure (child,
+ OPPOSITE_ORIENTATION (self->orientation),
+ child_size,
+ &child_minimum, &child_natural,
+ &child_minimum_baseline, &child_natural_baseline);
- if (child_minimum_baseline >= 0)
- {
- have_baseline = TRUE;
- computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline);
- computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline);
- computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline);
- computed_natural_above = MAX (computed_natural_above, child_natural_baseline);
- }
- else
- {
- computed_minimum = MAX (computed_minimum, child_minimum);
- computed_natural = MAX (computed_natural, child_natural);
+ if (child_minimum_baseline >= 0)
+ {
+ have_baseline = TRUE;
+ computed_minimum_below = MAX (computed_minimum_below, child_minimum - child_minimum_baseline);
+ computed_natural_below = MAX (computed_natural_below, child_natural - child_natural_baseline);
+ computed_minimum_above = MAX (computed_minimum_above, child_minimum_baseline);
+ computed_natural_above = MAX (computed_natural_above, child_natural_baseline);
+ }
+ else
+ {
+ computed_minimum = MAX (computed_minimum, child_minimum);
+ computed_natural = MAX (computed_natural, child_natural);
+ }
}
- i += 1;
}
if (have_baseline)
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index 3c3be85406..a82ec7bb77 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -1077,14 +1077,15 @@ get_static_size (GtkLabel *self,
int *minimum_baseline,
int *natural_baseline)
{
+ int minimum_default, natural_default;
PangoLayout *layout;
- layout = gtk_label_get_measuring_layout (self, NULL, -1);
+ get_default_widths (self, &minimum_default, &natural_default);
+
+ layout = gtk_label_get_measuring_layout (self, NULL, self->ellipsize ? natural_default : -1);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
- int minimum_default, natural_default;
-
pango_layout_get_size (layout, natural, NULL);
if (self->ellipsize)
{
@@ -1096,11 +1097,8 @@ get_static_size (GtkLabel *self,
else
*minimum = *natural;
- get_default_widths (self, &minimum_default, &natural_default);
if (minimum_default > *minimum)
*minimum = minimum_default;
- if (natural_default > -1)
- *natural = natural_default;
*natural = MAX (*minimum, *natural);
}
else
@@ -1180,7 +1178,6 @@ get_width_for_height (GtkLabel *self,
/* Natural width is natural width - or as wide as possible */
layout = gtk_label_get_measuring_layout (self, layout, natural_default);
pango_layout_get_size (layout, natural_width, NULL);
- *natural_width = MAX (*natural_width, natural_default);
*natural_width = MAX (*natural_width, *minimum_width);
}
else
diff --git a/gtk/gtksizerequest.c b/gtk/gtksizerequest.c
index 45770d5498..a0f066b997 100644
--- a/gtk/gtksizerequest.c
+++ b/gtk/gtksizerequest.c
@@ -139,7 +139,6 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
int *minimum_baseline,
int *natural_baseline)
{
- const gboolean baselines_requested = (minimum_baseline != NULL || natural_baseline != NULL);
SizeRequestCache *cache;
int min_size = 0;
int nat_size = 0;
@@ -361,7 +360,7 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
nat_size = adjusted_natural;
}
- if (baselines_requested && (min_baseline != -1 || nat_baseline != -1))
+ if (min_baseline != -1 || nat_baseline != -1)
{
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
diff --git a/testsuite/reftests/label-huge-max-width-chars.ref.ui b/testsuite/reftests/label-huge-max-width-chars.ref.ui
new file mode 100644
index 0000000000..ec722f56ce
--- /dev/null
+++ b/testsuite/reftests/label-huge-max-width-chars.ref.ui
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkWindow" id="window1">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label">Hello World</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/testsuite/reftests/label-huge-max-width-chars.ui b/testsuite/reftests/label-huge-max-width-chars.ui
new file mode 100644
index 0000000000..bf1237c1de
--- /dev/null
+++ b/testsuite/reftests/label-huge-max-width-chars.ui
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkWindow" id="window1">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label">Hello World</property>
+ <property name="max-width-chars">1000</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/testsuite/reftests/label-small-max-width-chars.ref.ui b/testsuite/reftests/label-small-max-width-chars.ref.ui
new file mode 100644
index 0000000000..ec722f56ce
--- /dev/null
+++ b/testsuite/reftests/label-small-max-width-chars.ref.ui
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkWindow" id="window1">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label">Hello World</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/testsuite/reftests/label-small-max-width-chars.ui b/testsuite/reftests/label-small-max-width-chars.ui
new file mode 100644
index 0000000000..d3236e8035
--- /dev/null
+++ b/testsuite/reftests/label-small-max-width-chars.ui
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkWindow" id="window1">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label">Hello World</property>
+ <property name="max-width-chars">2</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui b/testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui
new file mode 100644
index 0000000000..5ec6dea124
--- /dev/null
+++ b/testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkWindow" id="window1">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label">Hello World</property>
+ <property name="wrap">1</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/testsuite/reftests/label-wrapped-huge-max-width-chars.ui b/testsuite/reftests/label-wrapped-huge-max-width-chars.ui
new file mode 100644
index 0000000000..cc21161d61
--- /dev/null
+++ b/testsuite/reftests/label-wrapped-huge-max-width-chars.ui
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <object class="GtkWindow" id="window1">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="label">Hello World</property>
+ <property name="max-width-chars">1000</property>
+ <property name="wrap">1</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/testsuite/reftests/meson.build b/testsuite/reftests/meson.build
index 7917c1d388..83a06c9c80 100644
--- a/testsuite/reftests/meson.build
+++ b/testsuite/reftests/meson.build
@@ -347,6 +347,8 @@ testdata = [
'label-fonts.css',
'label-fonts.ref.ui',
'label-fonts.ui',
+ 'label-huge-max-width-chars.ref.ui',
+ 'label-huge-max-width-chars.ui',
'label-max-width-chars-and-halign-and-infinite-width.ui',
'label-max-width-chars-and-halign-and-infinite-width.ref.ui',
'label-shadows.css',
@@ -357,6 +359,8 @@ testdata = [
'label-sizing.ui',
'label-small-ellipsized.ref.ui',
'label-small-ellipsized.ui',
+ 'label-small-max-width-chars.ref.ui',
+ 'label-small-max-width-chars.ui',
'label-text-shadow-clipping.css',
'label-text-shadow-clipping.ref.ui',
'label-text-shadow-clipping.ui',
@@ -365,6 +369,8 @@ testdata = [
'label-text-shadow-changes-modify-clip.ui',
'label-width-chars-dont-shrink.ref.ui',
'label-width-chars-dont-shrink.ui',
+ 'label-wrapped-huge-max-width-chars.ref.ui',
+ 'label-wrapped-huge-max-width-chars.ui',
# this seems to make assumptions on text positioning
# that are not valid with subpixel positioning
#'label-wrap-justify.ref.ui',
@@ -500,6 +506,8 @@ testdata = [
'unresolvable.css',
'unresolvable.ref.ui',
'unresolvable.ui',
+ 'vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui',
+ 'vbox-with-2-wrapping-labels-where-one-should-wrap.ui',
'vbox-with-max-width-chars-label.ref.ui',
'vbox-with-max-width-chars-label.ui',
'window-border-width.ref.ui',
diff --git a/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui
new file mode 100644
index 0000000000..ec575c07d9
--- /dev/null
+++ b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ref.ui
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="gtk40">
+ <object class="GtkWindow">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkBox">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">1</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Hello
+World</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Hi Ho</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
+
diff --git a/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui
new file mode 100644
index 0000000000..f398308496
--- /dev/null
+++ b/testsuite/reftests/vbox-with-2-wrapping-labels-where-one-should-wrap.ui
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface domain="gtk40">
+ <object class="GtkWindow">
+ <property name="decorated">0</property>
+ <child>
+ <object class="GtkBox">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">1</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Hello World</property>
+ <property name="wrap">1</property>
+ <property name="max-width-chars">1</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label">Hi Ho</property>
+ <property name="wrap">1</property>
+ <property name="max-width-chars">1</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
+