st/scroll-view: Allocate the scrollbars 0-size instead of not painting them
StScrollView applies the policy of whether to show or hide the scroll bar, and with the AUTOMATIC policy the scroll bar should be hidden as soon as the content of the scroll view is small enough to fit without scrolling. Now we only know about the final size of the content when we're inside st_scroll_view_allocate(), so that's where we can decide whether the scroll bar should be visible or not. Clutter really doesn't like calling clutter_actor_show/hide() in the middle of an allocation cycle though, so what we do instead is saving the state into priv->vscrollbar_visible, and then just not painting the scroll bar based on that in a paint() vfunc override. This approach is not great for several reasons, it means we also have to override pick() and finally it means the paint volume of the scroll bar is incorrect. While the greatest solution to this would be to just hide/show the scroll bar inside the allocate() function as it is possible in gtk, we have an established pattern for this kind of case too: We usually allocate a 0-sized rect for the thing we want to hide, so let's do that instead. A nice side effect is that we can conveniently drop another paint() and pick() vfunc override. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2190>
This commit is contained in:
parent
8d7dc098b1
commit
a59a992daa
@ -268,41 +268,6 @@ st_scroll_view_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (st_scroll_view_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_paint (ClutterActor *actor,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
StScrollViewPrivate *priv =
|
||||
st_scroll_view_get_instance_private (ST_SCROLL_VIEW (actor));
|
||||
|
||||
st_widget_paint_background (ST_WIDGET (actor), paint_context);
|
||||
|
||||
if (priv->child)
|
||||
clutter_actor_paint (priv->child, paint_context);
|
||||
if (priv->hscrollbar_visible)
|
||||
clutter_actor_paint (priv->hscroll, paint_context);
|
||||
if (priv->vscrollbar_visible)
|
||||
clutter_actor_paint (priv->vscroll, paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
st_scroll_view_pick (ClutterActor *actor,
|
||||
ClutterPickContext *pick_context)
|
||||
{
|
||||
StScrollViewPrivate *priv =
|
||||
st_scroll_view_get_instance_private (ST_SCROLL_VIEW (actor));
|
||||
|
||||
/* Chain up so we get a bounding box pained (if we are reactive) */
|
||||
CLUTTER_ACTOR_CLASS (st_scroll_view_parent_class)->pick (actor, pick_context);
|
||||
|
||||
if (priv->child)
|
||||
clutter_actor_pick (priv->child, pick_context);
|
||||
if (priv->hscrollbar_visible)
|
||||
clutter_actor_pick (priv->hscroll, pick_context);
|
||||
if (priv->vscrollbar_visible)
|
||||
clutter_actor_pick (priv->vscroll, pick_context);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
st_scroll_view_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
@ -624,6 +589,8 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
*/
|
||||
|
||||
/* Vertical scrollbar */
|
||||
if (vscrollbar_visible)
|
||||
{
|
||||
if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL)
|
||||
{
|
||||
child_box.x1 = content_box.x1;
|
||||
@ -638,8 +605,16 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
child_box.y2 = content_box.y2 - (hscrollbar_visible ? sb_height : 0);
|
||||
|
||||
clutter_actor_allocate (priv->vscroll, &child_box);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActorBox empty_box = { 0, };
|
||||
clutter_actor_allocate (priv->vscroll, &empty_box);
|
||||
}
|
||||
|
||||
/* Horizontal scrollbar */
|
||||
if (hscrollbar_visible)
|
||||
{
|
||||
if (clutter_actor_get_text_direction (actor) == CLUTTER_TEXT_DIRECTION_RTL)
|
||||
{
|
||||
child_box.x1 = content_box.x1 + (vscrollbar_visible ? sb_width : 0);
|
||||
@ -654,6 +629,12 @@ st_scroll_view_allocate (ClutterActor *actor,
|
||||
child_box.y2 = content_box.y2;
|
||||
|
||||
clutter_actor_allocate (priv->hscroll, &child_box);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActorBox empty_box = { 0, };
|
||||
clutter_actor_allocate (priv->hscroll, &empty_box);
|
||||
}
|
||||
|
||||
/* In case the scrollbar policy is NEVER or EXTERNAL or scrollbars
|
||||
* should be overlaid, we don't trim the content box allocation by
|
||||
@ -868,8 +849,6 @@ st_scroll_view_class_init (StScrollViewClass *klass)
|
||||
object_class->set_property = st_scroll_view_set_property;
|
||||
object_class->dispose = st_scroll_view_dispose;
|
||||
|
||||
actor_class->paint = st_scroll_view_paint;
|
||||
actor_class->pick = st_scroll_view_pick;
|
||||
actor_class->get_paint_volume = st_scroll_view_get_paint_volume;
|
||||
actor_class->get_preferred_width = st_scroll_view_get_preferred_width;
|
||||
actor_class->get_preferred_height = st_scroll_view_get_preferred_height;
|
||||
|
Loading…
x
Reference in New Issue
Block a user