[gnome-shell/gnome-3-32] st: Delay handling of :first/:last-child changes
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/gnome-3-32] st: Delay handling of :first/:last-child changes
- Date: Tue, 14 May 2019 18:32:14 +0000 (UTC)
commit e43c8f63642e805b0f4a5935341551f68ef69f99
Author: Florian Müllner <fmuellner gnome org>
Date: Thu May 2 21:12:01 2019 +0200
st: Delay handling of :first/:last-child changes
Updating the :first/:last-child pseudo classes can result in a lot
of unnecessary style changes when bulk-adding children to a container,
as every child ends up as the new last child.
Address this by deferring the style change to an idle, so we only do
the work once for the actual first and last child.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/529
src/st/st-widget.c | 83 +++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 63 insertions(+), 20 deletions(-)
---
diff --git a/src/st/st-widget.c b/src/st/st-widget.c
index b20148906..b88b6f498 100644
--- a/src/st/st-widget.c
+++ b/src/st/st-widget.c
@@ -65,6 +65,8 @@ struct _StWidgetPrivate
StThemeNodeTransition *transition_animation;
guint is_style_dirty : 1;
+ guint first_child_dirty : 1;
+ guint last_child_dirty : 1;
guint draw_bg_color : 1;
guint draw_border_internal : 1;
guint track_hover : 1;
@@ -72,6 +74,7 @@ struct _StWidgetPrivate
guint can_focus : 1;
gulong texture_file_changed_id;
+ guint update_child_styles_id;
AtkObject *accessible;
AtkRole accessible_role;
@@ -323,6 +326,8 @@ st_widget_dispose (GObject *gobject)
g_clear_object (&priv->last_visible_child);
G_OBJECT_CLASS (st_widget_parent_class)->dispose (gobject);
+
+ g_clear_handle_id (&priv->update_child_styles_id, g_source_remove);
}
static void
@@ -1608,47 +1613,85 @@ find_nearest_visible_forward (ClutterActor *actor)
return next;
}
+static gboolean
+st_widget_update_child_styles (StWidget *widget)
+{
+ StWidgetPrivate *priv = st_widget_get_instance_private (widget);
+
+ if (priv->first_child_dirty)
+ {
+ ClutterActor *first_child;
+
+ priv->first_child_dirty = FALSE;
+
+ first_child = clutter_actor_get_first_child (CLUTTER_ACTOR (widget));
+ st_widget_set_first_visible_child (widget,
+ find_nearest_visible_forward (first_child));
+ }
+
+ if (priv->last_child_dirty)
+ {
+ ClutterActor *last_child;
+
+ priv->last_child_dirty = FALSE;
+
+ last_child = clutter_actor_get_last_child (CLUTTER_ACTOR (widget));
+ st_widget_set_last_visible_child (widget,
+ find_nearest_visible_backwards (last_child));
+ }
+
+ priv->update_child_styles_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+st_widget_queue_child_styles_update (StWidget *widget)
+{
+ StWidgetPrivate *priv = st_widget_get_instance_private (widget);
+
+ if (priv->update_child_styles_id != 0)
+ return;
+
+ priv->update_child_styles_id = g_idle_add ((GSourceFunc) st_widget_update_child_styles, widget);
+}
+
static void
st_widget_visible_notify (StWidget *widget,
GParamSpec *pspec,
gpointer data)
{
+ StWidgetPrivate *parent_priv;
ClutterActor *actor = CLUTTER_ACTOR (widget);
ClutterActor *parent = clutter_actor_get_parent (actor);
if (parent == NULL || !ST_IS_WIDGET (parent))
return;
+ parent_priv = st_widget_get_instance_private (ST_WIDGET (parent));
+
if (clutter_actor_is_visible (actor))
{
ClutterActor *before, *after;
before = clutter_actor_get_previous_sibling (actor);
if (find_nearest_visible_backwards (before) == NULL)
- st_widget_set_first_visible_child (ST_WIDGET (parent), actor);
+ parent_priv->first_child_dirty = TRUE;
after = clutter_actor_get_next_sibling (actor);
if (find_nearest_visible_forward (after) == NULL)
- st_widget_set_last_visible_child (ST_WIDGET (parent), actor);
+ parent_priv->last_child_dirty = TRUE;
}
else
{
if (st_widget_has_style_pseudo_class (widget, "first-child"))
- {
- ClutterActor *new_first;
-
- new_first = find_nearest_visible_forward (CLUTTER_ACTOR (widget));
- st_widget_set_first_visible_child (ST_WIDGET (parent), new_first);
- }
+ parent_priv->first_child_dirty = TRUE;
if (st_widget_has_style_pseudo_class (widget, "last-child"))
- {
- ClutterActor *new_last;
-
- new_last = find_nearest_visible_backwards (CLUTTER_ACTOR (widget));
- st_widget_set_last_visible_child (ST_WIDGET (parent), new_last);
- }
+ parent_priv->last_child_dirty = TRUE;
}
+
+ if (parent_priv->first_child_dirty || parent_priv->last_child_dirty)
+ st_widget_queue_child_styles_update (ST_WIDGET (parent));
}
static void
@@ -1656,10 +1699,10 @@ st_widget_first_child_notify (StWidget *widget,
GParamSpec *pspec,
gpointer data)
{
- ClutterActor *first_child;
+ StWidgetPrivate *priv = st_widget_get_instance_private (widget);
- first_child = clutter_actor_get_first_child (CLUTTER_ACTOR (widget));
- st_widget_set_first_visible_child (widget, find_nearest_visible_forward (first_child));
+ priv->first_child_dirty = TRUE;
+ st_widget_queue_child_styles_update (widget);
}
static void
@@ -1667,10 +1710,10 @@ st_widget_last_child_notify (StWidget *widget,
GParamSpec *pspec,
gpointer data)
{
- ClutterActor *last_child;
+ StWidgetPrivate *priv = st_widget_get_instance_private (widget);
- last_child = clutter_actor_get_last_child (CLUTTER_ACTOR (widget));
- st_widget_set_last_visible_child (widget, find_nearest_visible_backwards (last_child));
+ priv->last_child_dirty = TRUE;
+ st_widget_queue_child_styles_update (widget);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]