mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-28 14:31:10 +00:00
Merge branch 'wip/otte/for-master' into 'master'
lots of sizing fixes See merge request GNOME/gtk!4131
This commit is contained in:
commit
08d48201e9
@ -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">
|
||||
|
@ -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);
|
||||
|
||||
/* 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))
|
||||
{
|
||||
int min_opposite, nat_for_min;
|
||||
|
||||
if (!gtk_widget_should_layout (child))
|
||||
continue;
|
||||
|
||||
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);
|
||||
|
||||
children_minimum_size += sizes[i].minimum_size;
|
||||
i += 1;
|
||||
}
|
||||
g_assert ((nvis_children - 1) * spacing <= for_size);
|
||||
available = for_size - (nvis_children - 1) * spacing;
|
||||
|
||||
if (self->homogeneous)
|
||||
{
|
||||
/* We still need to run the above loop to populate the minimum sizes for
|
||||
* children that aren't going to fill.
|
||||
*/
|
||||
size_given_to_child = available / nvis_children;
|
||||
n_extra_widgets = available % nvis_children;
|
||||
|
||||
size_given_to_child = extra_space / nvis_children;
|
||||
n_extra_widgets = extra_space % nvis_children;
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
child != NULL;
|
||||
child = _gtk_widget_get_next_sibling (child))
|
||||
{
|
||||
if (!gtk_widget_should_layout (child))
|
||||
continue;
|
||||
|
||||
child_size = size_given_to_child;
|
||||
if (n_extra_widgets)
|
||||
{
|
||||
child_size++;
|
||||
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);
|
||||
|
||||
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);
|
||||
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
|
||||
{
|
||||
computed_minimum = MAX (computed_minimum, child_minimum);
|
||||
computed_natural = MAX (computed_natural, child_natural);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if (have_baseline)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
11
testsuite/reftests/label-huge-max-width-chars.ref.ui
Normal file
11
testsuite/reftests/label-huge-max-width-chars.ref.ui
Normal file
@ -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>
|
12
testsuite/reftests/label-huge-max-width-chars.ui
Normal file
12
testsuite/reftests/label-huge-max-width-chars.ui
Normal file
@ -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>
|
11
testsuite/reftests/label-small-max-width-chars.ref.ui
Normal file
11
testsuite/reftests/label-small-max-width-chars.ref.ui
Normal file
@ -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>
|
12
testsuite/reftests/label-small-max-width-chars.ui
Normal file
12
testsuite/reftests/label-small-max-width-chars.ui
Normal file
@ -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>
|
12
testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui
Normal file
12
testsuite/reftests/label-wrapped-huge-max-width-chars.ref.ui
Normal file
@ -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>
|
13
testsuite/reftests/label-wrapped-huge-max-width-chars.ui
Normal file
13
testsuite/reftests/label-wrapped-huge-max-width-chars.ui
Normal file
@ -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>
|
@ -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',
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user