GtkScrolledWindow: Bug 766569 - Make propagation of natural child sizes optional

Making propagation of child natural sizes mandatory (or default, even) was
evidently a mistake as this causes dynamic content in a scrolled window
to resize it's parent when the scrolled window is competing for space
with an adjacent widget.

This patch instead adds API to control whether natural width and
height of the child should be propagated through the scrolled windows
size requests.
This commit is contained in:
Tristan Van Berkom 2016-08-31 13:54:25 +09:00 committed by Matthias Clasen
parent 738b1e3eec
commit 0984d1622d
3 changed files with 184 additions and 10 deletions

View File

@ -3239,6 +3239,10 @@ gtk_scrolled_window_set_capture_button_press
gtk_scrolled_window_get_capture_button_press
gtk_scrolled_window_set_overlay_scrolling
gtk_scrolled_window_get_overlay_scrolling
gtk_scrolled_window_set_propagate_natural_width
gtk_scrolled_window_get_propagate_natural_width
gtk_scrolled_window_set_propagate_natural_height
gtk_scrolled_window_get_propagate_natural_height
<SUBSECTION Standard>
GTK_SCROLLED_WINDOW

View File

@ -233,14 +233,16 @@ struct _GtkScrolledWindowPrivate
GtkCornerType window_placement;
guint16 shadow_type;
guint hscrollbar_policy : 2;
guint vscrollbar_policy : 2;
guint hscrollbar_visible : 1;
guint vscrollbar_visible : 1;
guint focus_out : 1; /* used by ::move-focus-out implementation */
guint overlay_scrolling : 1;
guint use_indicators : 1;
guint auto_added_viewport : 1;
guint hscrollbar_policy : 2;
guint vscrollbar_policy : 2;
guint hscrollbar_visible : 1;
guint vscrollbar_visible : 1;
guint focus_out : 1; /* used by ::move-focus-out implementation */
guint overlay_scrolling : 1;
guint use_indicators : 1;
guint auto_added_viewport : 1;
guint propagate_natural_width : 1;
guint propagate_natural_height : 1;
gint min_content_width;
gint min_content_height;
@ -303,6 +305,8 @@ enum {
PROP_OVERLAY_SCROLLING,
PROP_MAX_CONTENT_WIDTH,
PROP_MAX_CONTENT_HEIGHT,
PROP_PROPAGATE_NATURAL_WIDTH,
PROP_PROPAGATE_NATURAL_HEIGHT,
NUM_PROPERTIES
};
@ -739,6 +743,42 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
-1, G_MAXINT, -1,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkScrolledWindow:propagate-natural-width:
*
* Whether the natural width of the child should be calculated and propagated
* through the scrolled windows requested natural width.
*
* This is useful in cases where an attempt should be made to allocate exactly
* enough space for the natural size of the child.
*
* Since: 3.22
*/
properties[PROP_PROPAGATE_NATURAL_WIDTH] =
g_param_spec_boolean ("propagate-natural-width",
P_("Propagate Natural Width"),
P_("Propagate Natural Width"),
FALSE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkScrolledWindow:propagate-natural-height:
*
* Whether the natural height of the child should be calculated and propagated
* through the scrolled windows requested natural height.
*
* This is useful in cases where an attempt should be made to allocate exactly
* enough space for the natural size of the child.
*
* Since: 3.22
*/
properties[PROP_PROPAGATE_NATURAL_HEIGHT] =
g_param_spec_boolean ("propagate-natural-height",
P_("Propagate Natural Height"),
P_("Propagate Natural Height"),
FALSE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
/**
@ -1798,7 +1838,8 @@ gtk_scrolled_window_measure (GtkCssGadget *gadget,
&min_child_size,
&nat_child_size);
natural_req.width += nat_child_size;
if (priv->propagate_natural_width)
natural_req.width += nat_child_size;
if (priv->hscrollbar_policy == GTK_POLICY_NEVER)
{
@ -1819,7 +1860,8 @@ gtk_scrolled_window_measure (GtkCssGadget *gadget,
&min_child_size,
&nat_child_size);
natural_req.height += nat_child_size;
if (priv->propagate_natural_height)
natural_req.height += nat_child_size;
if (priv->vscrollbar_policy == GTK_POLICY_NEVER)
{
@ -1836,6 +1878,10 @@ gtk_scrolled_window_measure (GtkCssGadget *gadget,
}
}
/* Ensure we make requests with natural size >= minimum size */
natural_req.height = MAX (minimum_req.height, natural_req.height);
natural_req.width = MAX (minimum_req.width, natural_req.width);
/*
* Now add to the requisition any additional space for surrounding scrollbars
* and the special scrollable border.
@ -2847,6 +2893,14 @@ gtk_scrolled_window_set_property (GObject *object,
gtk_scrolled_window_set_max_content_height (scrolled_window,
g_value_get_int (value));
break;
case PROP_PROPAGATE_NATURAL_WIDTH:
gtk_scrolled_window_set_propagate_natural_width (scrolled_window,
g_value_get_boolean (value));
break;
case PROP_PROPAGATE_NATURAL_HEIGHT:
gtk_scrolled_window_set_propagate_natural_height (scrolled_window,
g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -2905,6 +2959,12 @@ gtk_scrolled_window_get_property (GObject *object,
case PROP_MAX_CONTENT_HEIGHT:
g_value_set_int (value, priv->max_content_height);
break;
case PROP_PROPAGATE_NATURAL_WIDTH:
g_value_set_boolean (value, priv->propagate_natural_width);
break;
case PROP_PROPAGATE_NATURAL_HEIGHT:
g_value_set_boolean (value, priv->propagate_natural_height);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -4731,3 +4791,101 @@ gtk_scrolled_window_get_max_content_height (GtkScrolledWindow *scrolled_window)
return scrolled_window->priv->max_content_height;
}
/**
* gtk_scrolled_window_set_propagate_natural_width:
* @scrolled_window: a #GtkScrolledWindow
* @propagate: whether to propagate natural width
*
* Sets whether the natural width of the child should be calculated and propagated
* through the scrolled windows requested natural width.
*
* Since: 3.22
*/
void
gtk_scrolled_window_set_propagate_natural_width (GtkScrolledWindow *scrolled_window,
gboolean propagate)
{
GtkScrolledWindowPrivate *priv;
g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
priv = scrolled_window->priv;
propagate = !!propagate;
if (priv->propagate_natural_width != propagate)
{
priv->propagate_natural_width = propagate;
g_object_notify_by_pspec (G_OBJECT (scrolled_window), properties [PROP_PROPAGATE_NATURAL_WIDTH]);
gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
}
}
/**
* gtk_scrolled_window_get_propagate_natural_width:
* @scrolled_window: a #GtkScrolledWindow
*
* Reports whether the natural width of the child will be calculated and propagated
* through the scrolled windows requested natural width.
*
* Returns: whether natural width propagation is enabled.
*
* Since: 3.22
*/
gint
gtk_scrolled_window_get_propagate_natural_width (GtkScrolledWindow *scrolled_window)
{
g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), -1);
return scrolled_window->priv->propagate_natural_width;
}
/**
* gtk_scrolled_window_set_propagate_natural_height:
* @scrolled_window: a #GtkScrolledWindow
* @propagate: whether to propagate natural height
*
* Sets whether the natural height of the child should be calculated and propagated
* through the scrolled windows requested natural height.
*
* Since: 3.22
*/
void
gtk_scrolled_window_set_propagate_natural_height (GtkScrolledWindow *scrolled_window,
gboolean propagate)
{
GtkScrolledWindowPrivate *priv;
g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window));
priv = scrolled_window->priv;
propagate = !!propagate;
if (priv->propagate_natural_height != propagate)
{
priv->propagate_natural_height = propagate;
g_object_notify_by_pspec (G_OBJECT (scrolled_window), properties [PROP_PROPAGATE_NATURAL_HEIGHT]);
gtk_widget_queue_resize (GTK_WIDGET (scrolled_window));
}
}
/**
* gtk_scrolled_window_get_propagate_natural_height:
* @scrolled_window: a #GtkScrolledWindow
*
* Reports whether the natural height of the child will be calculated and propagated
* through the scrolled windows requested natural height.
*
* Returns: whether natural height propagation is enabled.
*
* Since: 3.22
*/
gint
gtk_scrolled_window_get_propagate_natural_height (GtkScrolledWindow *scrolled_window)
{
g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), -1);
return scrolled_window->priv->propagate_natural_height;
}

View File

@ -226,6 +226,18 @@ void gtk_scrolled_window_set_max_content_height (GtkScrolledWindow *sc
GDK_AVAILABLE_IN_3_22
gint gtk_scrolled_window_get_max_content_height (GtkScrolledWindow *scrolled_window);
GDK_AVAILABLE_IN_3_22
void gtk_scrolled_window_set_propagate_natural_width (GtkScrolledWindow *scrolled_window,
gboolean propagate);
GDK_AVAILABLE_IN_3_22
gboolean gtk_scrolled_window_get_propagate_natural_width (GtkScrolledWindow *scrolled_window);
GDK_AVAILABLE_IN_3_22
void gtk_scrolled_window_set_propagate_natural_height (GtkScrolledWindow *scrolled_window,
gboolean propagate);
GDK_AVAILABLE_IN_3_22
gboolean gtk_scrolled_window_get_propagate_natural_height (GtkScrolledWindow *scrolled_window);
G_END_DECLS