From 479c14c766041c5dfce541e67dcd7481984146f4 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Wed, 11 Dec 2019 12:35:29 -0300 Subject: [PATCH] st/box-layout: Reimplement as a StViewport subclass With StViewport doing most of the heavy-lifting, StBoxLayout can be cleaned up as a StViewport subclass. https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/929 --- src/st/st-box-layout.c | 464 +---------------------------------------- src/st/st-box-layout.h | 5 +- 2 files changed, 5 insertions(+), 464 deletions(-) diff --git a/src/st/st-box-layout.c b/src/st/st-box-layout.c index 019aebd76..57705d320 100644 --- a/src/st/st-box-layout.c +++ b/src/st/st-box-layout.c @@ -57,16 +57,12 @@ static void st_box_container_iface_init (ClutterContainerIface *iface); -static void st_box_scrollable_interface_init (StScrollableInterface *iface); enum { PROP_0, PROP_VERTICAL, PROP_PACK_START, - - PROP_HADJUST, - PROP_VADJUST }; struct _StBoxLayoutPrivate @@ -75,104 +71,10 @@ struct _StBoxLayoutPrivate StAdjustment *vadjustment; }; -G_DEFINE_TYPE_WITH_CODE (StBoxLayout, st_box_layout, ST_TYPE_WIDGET, +G_DEFINE_TYPE_WITH_CODE (StBoxLayout, st_box_layout, ST_TYPE_VIEWPORT, G_ADD_PRIVATE (StBoxLayout) G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER, - st_box_container_iface_init) - G_IMPLEMENT_INTERFACE (ST_TYPE_SCROLLABLE, - st_box_scrollable_interface_init)); - -/* - * StScrollable Interface Implementation - */ -static void -adjustment_value_notify_cb (StAdjustment *adjustment, - GParamSpec *pspec, - StBoxLayout *box) -{ - clutter_actor_queue_relayout (CLUTTER_ACTOR (box)); -} - -static void -scrollable_set_adjustments (StScrollable *scrollable, - StAdjustment *hadjustment, - StAdjustment *vadjustment) -{ - StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (scrollable)->priv; - - g_object_freeze_notify (G_OBJECT (scrollable)); - - if (hadjustment != priv->hadjustment) - { - if (priv->hadjustment) - { - g_signal_handlers_disconnect_by_func (priv->hadjustment, - adjustment_value_notify_cb, - scrollable); - g_object_unref (priv->hadjustment); - } - - if (hadjustment) - { - g_object_ref (hadjustment); - g_signal_connect (hadjustment, "notify::value", - G_CALLBACK (adjustment_value_notify_cb), - scrollable); - } - - priv->hadjustment = hadjustment; - g_object_notify (G_OBJECT (scrollable), "hadjustment"); - } - - if (vadjustment != priv->vadjustment) - { - if (priv->vadjustment) - { - g_signal_handlers_disconnect_by_func (priv->vadjustment, - adjustment_value_notify_cb, - scrollable); - g_object_unref (priv->vadjustment); - } - - if (vadjustment) - { - g_object_ref (vadjustment); - g_signal_connect (vadjustment, "notify::value", - G_CALLBACK (adjustment_value_notify_cb), - scrollable); - } - - priv->vadjustment = vadjustment; - g_object_notify (G_OBJECT (scrollable), "vadjustment"); - } - - g_object_thaw_notify (G_OBJECT (scrollable)); -} - -static void -scrollable_get_adjustments (StScrollable *scrollable, - StAdjustment **hadjustment, - StAdjustment **vadjustment) -{ - StBoxLayoutPrivate *priv; - - priv = (ST_BOX_LAYOUT (scrollable))->priv; - - if (hadjustment) - *hadjustment = priv->hadjustment; - - if (vadjustment) - *vadjustment = priv->vadjustment; -} - - - -static void -st_box_scrollable_interface_init (StScrollableInterface *iface) -{ - iface->set_adjustments = scrollable_set_adjustments; - iface->get_adjustments = scrollable_get_adjustments; -} + st_box_container_iface_init)); static void st_box_container_iface_init (ClutterContainerIface *iface) @@ -188,7 +90,6 @@ st_box_layout_get_property (GObject *object, GParamSpec *pspec) { ClutterLayoutManager *layout; - StAdjustment *adjustment; ClutterOrientation orientation; switch (property_id) @@ -204,16 +105,6 @@ st_box_layout_get_property (GObject *object, g_value_set_boolean (value, clutter_box_layout_get_pack_start (CLUTTER_BOX_LAYOUT (layout))); break; - case PROP_HADJUST: - scrollable_get_adjustments (ST_SCROLLABLE (object), &adjustment, NULL); - g_value_set_object (value, adjustment); - break; - - case PROP_VADJUST: - scrollable_get_adjustments (ST_SCROLLABLE (object), NULL, &adjustment); - g_value_set_object (value, adjustment); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } @@ -237,343 +128,11 @@ st_box_layout_set_property (GObject *object, st_box_layout_set_pack_start (box, g_value_get_boolean (value)); break; - case PROP_HADJUST: - scrollable_set_adjustments (ST_SCROLLABLE (object), - g_value_get_object (value), - box->priv->vadjustment); - break; - - case PROP_VADJUST: - scrollable_set_adjustments (ST_SCROLLABLE (object), - box->priv->hadjustment, - g_value_get_object (value)); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } -static void -st_box_layout_dispose (GObject *object) -{ - StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (object)->priv; - - if (priv->hadjustment) - { - g_object_unref (priv->hadjustment); - priv->hadjustment = NULL; - } - - if (priv->vadjustment) - { - g_object_unref (priv->vadjustment); - priv->vadjustment = NULL; - } - - G_OBJECT_CLASS (st_box_layout_parent_class)->dispose (object); -} - -static void -st_box_layout_allocate (ClutterActor *actor, - const ClutterActorBox *box, - ClutterAllocationFlags flags) -{ - StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (actor)->priv; - StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); - ClutterLayoutManager *layout = clutter_actor_get_layout_manager (actor); - ClutterActorBox viewport_content_box; - ClutterActorBox content_box; - gfloat avail_width, avail_height, min_width, natural_width, min_height, natural_height; - - st_theme_node_get_content_box (theme_node, box, &viewport_content_box); - clutter_actor_box_get_size (&viewport_content_box, &avail_width, &avail_height); - - clutter_layout_manager_get_preferred_width (layout, CLUTTER_CONTAINER (actor), - avail_height, - &min_width, &natural_width); - clutter_layout_manager_get_preferred_height (layout, CLUTTER_CONTAINER (actor), - MAX (avail_width, min_width), - &min_height, &natural_height); - - /* Because StBoxLayout implements StScrollable, the allocation box passed here - * may not match the minimum sizes reported by the layout manager. When that - * happens, the content box needs to be adjusted to match the reported minimum - * sizes before being passed to clutter_layout_manager_allocate() */ - clutter_actor_set_allocation (actor, box, flags); - - content_box = viewport_content_box; - content_box.x2 += MAX (0, min_width - avail_width); - content_box.y2 += MAX (0, min_height - avail_height); - - clutter_layout_manager_allocate (layout, CLUTTER_CONTAINER (actor), - &content_box, flags); - - /* update adjustments for scrolling */ - if (priv->vadjustment) - { - gdouble prev_value; - - g_object_set (G_OBJECT (priv->vadjustment), - "lower", 0.0, - "upper", MAX (min_height, avail_height), - "page-size", avail_height, - "step-increment", avail_height / 6, - "page-increment", avail_height - avail_height / 6, - NULL); - - prev_value = st_adjustment_get_value (priv->vadjustment); - st_adjustment_set_value (priv->vadjustment, prev_value); - } - - if (priv->hadjustment) - { - gdouble prev_value; - - g_object_set (G_OBJECT (priv->hadjustment), - "lower", 0.0, - "upper", MAX (min_width, avail_width), - "page-size", avail_width, - "step-increment", avail_width / 6, - "page-increment", avail_width - avail_width / 6, - NULL); - - prev_value = st_adjustment_get_value (priv->hadjustment); - st_adjustment_set_value (priv->hadjustment, prev_value); - } -} - -static void -st_box_layout_apply_transform (ClutterActor *a, - CoglMatrix *m) -{ - StBoxLayoutPrivate *priv = ST_BOX_LAYOUT (a)->priv; - gdouble x, y; - - CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->apply_transform (a, m); - - if (priv->hadjustment) - x = st_adjustment_get_value (priv->hadjustment); - else - x = 0; - - if (priv->vadjustment) - y = st_adjustment_get_value (priv->vadjustment); - else - y = 0; - - cogl_matrix_translate (m, (int) -x, (int) -y, 0); -} - -/* If we are translated, then we need to translate back before chaining - * up or the background and borders will be drawn in the wrong place */ -static void -get_border_paint_offsets (StBoxLayout *self, - double *x, - double *y) -{ - StBoxLayoutPrivate *priv = self->priv; - - if (priv->hadjustment) - *x = st_adjustment_get_value (priv->hadjustment); - else - *x = 0; - - if (priv->vadjustment) - *y = st_adjustment_get_value (priv->vadjustment); - else - *y = 0; -} - - -static void -st_box_layout_paint (ClutterActor *actor, - ClutterPaintContext *paint_context) -{ - StBoxLayout *self = ST_BOX_LAYOUT (actor); - StBoxLayoutPrivate *priv = self->priv; - StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); - gdouble x, y; - ClutterActorBox allocation_box; - ClutterActorBox content_box; - ClutterActor *child; - CoglFramebuffer *fb = clutter_paint_context_get_framebuffer (paint_context); - - get_border_paint_offsets (self, &x, &y); - if (x != 0 || y != 0) - { - cogl_framebuffer_push_matrix (fb); - cogl_framebuffer_translate (fb, (int)x, (int)y, 0); - } - - st_widget_paint_background (ST_WIDGET (actor), paint_context); - - if (x != 0 || y != 0) - { - cogl_framebuffer_pop_matrix (fb); - } - - if (clutter_actor_get_n_children (actor) == 0) - return; - - clutter_actor_get_allocation_box (actor, &allocation_box); - st_theme_node_get_content_box (theme_node, &allocation_box, &content_box); - - content_box.x1 += x; - content_box.y1 += y; - content_box.x2 += x; - content_box.y2 += y; - - /* The content area forms the viewport into the scrolled contents, while - * the borders and background stay in place; after drawing the borders and - * background, we clip to the content area */ - if (priv->hadjustment || priv->vadjustment) - cogl_framebuffer_push_rectangle_clip (fb, - (int)content_box.x1, - (int)content_box.y1, - (int)content_box.x2, - (int)content_box.y2); - - for (child = clutter_actor_get_first_child (actor); - child != NULL; - child = clutter_actor_get_next_sibling (child)) - clutter_actor_paint (child, paint_context); - - if (priv->hadjustment || priv->vadjustment) - cogl_framebuffer_pop_clip (fb); -} - -static void -st_box_layout_pick (ClutterActor *actor, - ClutterPickContext *pick_context) -{ - StBoxLayout *self = ST_BOX_LAYOUT (actor); - StBoxLayoutPrivate *priv = self->priv; - StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); - gdouble x, y; - ClutterActorBox allocation_box; - ClutterActorBox content_box; - ClutterActor *child; - CoglFramebuffer *fb = clutter_pick_context_get_framebuffer (pick_context); - - get_border_paint_offsets (self, &x, &y); - if (x != 0 || y != 0) - { - cogl_framebuffer_push_matrix (fb); - cogl_framebuffer_translate (fb, (int)x, (int)y, 0); - } - - CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->pick (actor, pick_context); - - if (x != 0 || y != 0) - { - cogl_framebuffer_pop_matrix (fb); - } - - if (clutter_actor_get_n_children (actor) == 0) - return; - - clutter_actor_get_allocation_box (actor, &allocation_box); - st_theme_node_get_content_box (theme_node, &allocation_box, &content_box); - - content_box.x1 += x; - content_box.y1 += y; - content_box.x2 += x; - content_box.y2 += y; - - if (priv->hadjustment || priv->vadjustment) - cogl_framebuffer_push_rectangle_clip (fb, - (int)content_box.x1, - (int)content_box.y1, - (int)content_box.x2, - (int)content_box.y2); - - for (child = clutter_actor_get_first_child (actor); - child != NULL; - child = clutter_actor_get_next_sibling (child)) - clutter_actor_pick (child, pick_context); - - if (priv->hadjustment || priv->vadjustment) - cogl_framebuffer_pop_clip (fb); -} - -static gboolean -st_box_layout_get_paint_volume (ClutterActor *actor, - ClutterPaintVolume *volume) -{ - StBoxLayout *self = ST_BOX_LAYOUT (actor); - gdouble x, y, lower, upper; - StBoxLayoutPrivate *priv = self->priv; - StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor)); - ClutterActorBox allocation_box; - ClutterActorBox content_box; - graphene_point3d_t origin; - - /* Setting the paint volume does not make sense when we don't have any allocation */ - if (!clutter_actor_has_allocation (actor)) - return FALSE; - - /* When have an adjustment we are clipped to the content box, so base - * our paint volume on that. */ - if (priv->hadjustment || priv->vadjustment) - { - gdouble width, height; - - clutter_actor_get_allocation_box (actor, &allocation_box); - st_theme_node_get_content_box (theme_node, &allocation_box, &content_box); - origin.x = content_box.x1 - allocation_box.x1; - origin.y = content_box.y1 - allocation_box.y2; - origin.z = 0.f; - - if (priv->hadjustment) - { - g_object_get (priv->hadjustment, - "lower", &lower, - "upper", &upper, - NULL); - width = upper - lower; - } - else - { - width = content_box.x2 - content_box.x1; - } - - if (priv->vadjustment) - { - g_object_get (priv->vadjustment, - "lower", &lower, - "upper", &upper, - NULL); - height = upper - lower; - } - else - { - height = content_box.y2 - content_box.y1; - } - - clutter_paint_volume_set_width (volume, width); - clutter_paint_volume_set_height (volume, height); - } - else if (!CLUTTER_ACTOR_CLASS (st_box_layout_parent_class)->get_paint_volume (actor, volume)) - return FALSE; - - /* When scrolled, st_box_layout_apply_transform() includes the scroll offset - * and affects paint volumes. This is right for our children, but our paint volume - * is determined by our allocation and borders and doesn't scroll, so we need - * to reverse-compensate here, the same as we do when painting. - */ - get_border_paint_offsets (self, &x, &y); - if (x != 0 || y != 0) - { - clutter_paint_volume_get_origin (volume, &origin); - origin.x += x; - origin.y += y; - clutter_paint_volume_set_origin (volume, &origin); - } - - return TRUE; -} - static void st_box_layout_style_changed (StWidget *self) { @@ -623,20 +182,11 @@ static void st_box_layout_class_init (StBoxLayoutClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); StWidgetClass *widget_class = ST_WIDGET_CLASS (klass); GParamSpec *pspec; object_class->get_property = st_box_layout_get_property; object_class->set_property = st_box_layout_set_property; - object_class->dispose = st_box_layout_dispose; - - actor_class->allocate = st_box_layout_allocate; - actor_class->apply_transform = st_box_layout_apply_transform; - - actor_class->paint = st_box_layout_paint; - actor_class->get_paint_volume = st_box_layout_get_paint_volume; - actor_class->pick = st_box_layout_pick; widget_class->style_changed = st_box_layout_style_changed; @@ -654,16 +204,6 @@ st_box_layout_class_init (StBoxLayoutClass *klass) FALSE, ST_PARAM_READWRITE); g_object_class_install_property (object_class, PROP_PACK_START, pspec); - - /* StScrollable properties */ - g_object_class_override_property (object_class, - PROP_HADJUST, - "hadjustment"); - - g_object_class_override_property (object_class, - PROP_VADJUST, - "vadjustment"); - } static void diff --git a/src/st/st-box-layout.h b/src/st/st-box-layout.h index 3e127b942..82f5a7045 100644 --- a/src/st/st-box-layout.h +++ b/src/st/st-box-layout.h @@ -26,11 +26,12 @@ #define _ST_BOX_LAYOUT_H #include +#include G_BEGIN_DECLS #define ST_TYPE_BOX_LAYOUT st_box_layout_get_type() -G_DECLARE_FINAL_TYPE (StBoxLayout, st_box_layout, ST, BOX_LAYOUT, StWidget) +G_DECLARE_FINAL_TYPE (StBoxLayout, st_box_layout, ST, BOX_LAYOUT, StViewport) typedef struct _StBoxLayout StBoxLayout; typedef struct _StBoxLayoutPrivate StBoxLayoutPrivate; @@ -44,7 +45,7 @@ typedef struct _StBoxLayoutPrivate StBoxLayoutPrivate; struct _StBoxLayout { /*< private >*/ - StWidget parent; + StViewport parent; StBoxLayoutPrivate *priv; };