[gnome-shell/wip/fmuellner/first-last-child: 259/259] st: Only consider visible children for :first/:last-child
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/fmuellner/first-last-child: 259/259] st: Only consider visible children for :first/:last-child
- Date: Sat, 2 Mar 2019 12:20:01 +0000 (UTC)
commit 4d0a742d64bd7e47015ef23b443d9d32e9225313
Author: Florian Müllner <fmuellner gnome org>
Date: Tue Nov 27 02:21:37 2018 +0100
st: Only consider visible children for :first/:last-child
While mapping the :first/:last-child pseudo classes directly to the
ClutterActor:first-child/:last-child properties allows for an easy
implementation, it is unexpected that rules can appear to not have
an effect because the selected child is hidden. GTK's behavior of
applying the classes to visible children makes much more sense, so
change our implementation to do the same.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/312
src/st/st-widget.c | 165 +++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 127 insertions(+), 38 deletions(-)
---
diff --git a/src/st/st-widget.c b/src/st/st-widget.c
index eea5f7f3b..f5ca8928a 100644
--- a/src/st/st-widget.c
+++ b/src/st/st-widget.c
@@ -80,11 +80,8 @@ struct _StWidgetPrivate
ClutterActor *label_actor;
gchar *accessible_name;
- /* Even though Clutter has first_child/last_child properties,
- * we need to keep track of the old first/last children so
- * that we can remove the pseudo classes on them. */
- StWidget *prev_last_child;
- StWidget *prev_first_child;
+ StWidget *last_visible_child;
+ StWidget *first_visible_child;
StThemeNodePaintState paint_states[2];
int current_paint_state : 2;
@@ -322,8 +319,8 @@ st_widget_dispose (GObject *gobject)
priv->texture_file_changed_id = 0;
}
- g_clear_object (&priv->prev_first_child);
- g_clear_object (&priv->prev_last_child);
+ g_clear_object (&priv->first_visible_child);
+ g_clear_object (&priv->last_visible_child);
G_OBJECT_CLASS (st_widget_parent_class)->dispose (gobject);
}
@@ -1488,6 +1485,64 @@ st_widget_get_resource_scale (StWidget *widget,
resource_scale);
}
+static void
+st_widget_set_first_visible_child (StWidget *widget,
+ ClutterActor *actor)
+{
+ StWidgetPrivate *priv = st_widget_get_instance_private (widget);
+
+ if (priv->first_visible_child == NULL && actor == NULL)
+ return;
+
+ if (priv->first_visible_child != NULL &&
+ CLUTTER_ACTOR (priv->first_visible_child) == actor)
+ return;
+
+ if (priv->first_visible_child != NULL)
+ {
+ st_widget_remove_style_pseudo_class (priv->first_visible_child, "first-child");
+ g_clear_object (&priv->first_visible_child);
+ }
+
+ if (actor == NULL)
+ return;
+
+ if (ST_IS_WIDGET (actor))
+ {
+ st_widget_add_style_pseudo_class (ST_WIDGET (actor), "first-child");
+ priv->first_visible_child = g_object_ref (ST_WIDGET (actor));
+ }
+}
+
+static void
+st_widget_set_last_visible_child (StWidget *widget,
+ ClutterActor *actor)
+{
+ StWidgetPrivate *priv = st_widget_get_instance_private (widget);
+
+ if (priv->last_visible_child == NULL && actor == NULL)
+ return;
+
+ if (priv->last_visible_child != NULL &&
+ CLUTTER_ACTOR (priv->last_visible_child) == actor)
+ return;
+
+ if (priv->last_visible_child != NULL)
+ {
+ st_widget_remove_style_pseudo_class (priv->last_visible_child, "last-child");
+ g_clear_object (&priv->last_visible_child);
+ }
+
+ if (actor == NULL)
+ return;
+
+ if (ST_IS_WIDGET (actor))
+ {
+ st_widget_add_style_pseudo_class (ST_WIDGET (actor), "last-child");
+ priv->last_visible_child = g_object_ref (ST_WIDGET (actor));
+ }
+}
+
static void
st_widget_name_notify (StWidget *widget,
GParamSpec *pspec,
@@ -1529,56 +1584,89 @@ st_widget_reactive_notify (StWidget *widget,
st_widget_sync_hover(widget);
}
+static ClutterActor *
+find_nearest_visible_backwards (ClutterActor *actor)
+{
+ ClutterActor *prev = actor;
+
+ while (prev != NULL && !clutter_actor_is_visible (prev))
+ prev = clutter_actor_get_previous_sibling (prev);
+ return prev;
+}
+
+static ClutterActor *
+find_nearest_visible_forward (ClutterActor *actor)
+{
+ ClutterActor *next = actor;
+
+ while (next != NULL && !clutter_actor_is_visible (next))
+ next = clutter_actor_get_next_sibling (next);
+ return next;
+}
+
static void
-st_widget_first_child_notify (StWidget *widget,
- GParamSpec *pspec,
- gpointer data)
+st_widget_visible_notify (StWidget *widget,
+ GParamSpec *pspec,
+ gpointer data)
{
- StWidgetPrivate *priv = st_widget_get_instance_private (widget);
- ClutterActor *first_child;
+ ClutterActor *actor = CLUTTER_ACTOR (widget);
+ ClutterActor *parent = clutter_actor_get_parent (actor);
+
+ if (parent == NULL || !ST_IS_WIDGET (parent))
+ return;
- if (priv->prev_first_child != NULL)
+ if (clutter_actor_is_visible (actor))
{
- st_widget_remove_style_pseudo_class (priv->prev_first_child, "first-child");
- g_clear_object (&priv->prev_first_child);
+ 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);
+
+ after = clutter_actor_get_next_sibling (actor);
+ if (find_nearest_visible_forward (after) == NULL)
+ st_widget_set_last_visible_child (ST_WIDGET (parent), actor);
}
+ else
+ {
+ if (st_widget_has_style_pseudo_class (widget, "first-child"))
+ {
+ ClutterActor *new_first;
- first_child = clutter_actor_get_first_child (CLUTTER_ACTOR (widget));
+ new_first = find_nearest_visible_forward (CLUTTER_ACTOR (widget));
+ st_widget_set_first_visible_child (ST_WIDGET (parent), new_first);
+ }
- if (first_child == NULL)
- return;
+ if (st_widget_has_style_pseudo_class (widget, "last-child"))
+ {
+ ClutterActor *new_last;
- if (ST_IS_WIDGET (first_child))
- {
- st_widget_add_style_pseudo_class (ST_WIDGET (first_child), "first-child");
- priv->prev_first_child = g_object_ref (ST_WIDGET (first_child));
+ new_last = find_nearest_visible_backwards (CLUTTER_ACTOR (widget));
+ st_widget_set_last_visible_child (ST_WIDGET (parent), new_last);
+ }
}
}
+static void
+st_widget_first_child_notify (StWidget *widget,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ ClutterActor *first_child;
+
+ first_child = clutter_actor_get_first_child (CLUTTER_ACTOR (widget));
+ st_widget_set_first_visible_child (widget, find_nearest_visible_forward (first_child));
+}
+
static void
st_widget_last_child_notify (StWidget *widget,
GParamSpec *pspec,
gpointer data)
{
- StWidgetPrivate *priv = st_widget_get_instance_private (widget);
ClutterActor *last_child;
- if (priv->prev_last_child != NULL)
- {
- st_widget_remove_style_pseudo_class (priv->prev_last_child, "last-child");
- g_clear_object (&priv->prev_last_child);
- }
-
last_child = clutter_actor_get_last_child (CLUTTER_ACTOR (widget));
-
- if (last_child == NULL)
- return;
-
- if (ST_IS_WIDGET (last_child))
- {
- st_widget_add_style_pseudo_class (ST_WIDGET (last_child), "last-child");
- priv->prev_last_child = g_object_ref (ST_WIDGET (last_child));
- }
+ st_widget_set_last_visible_child (widget, find_nearest_visible_backwards (last_child));
}
static void
@@ -1596,6 +1684,7 @@ st_widget_init (StWidget *actor)
g_signal_connect (actor, "notify::resource-scale", G_CALLBACK (st_widget_resource_scale_notify), NULL);
g_signal_connect (actor, "notify::reactive", G_CALLBACK (st_widget_reactive_notify), NULL);
+ g_signal_connect (actor, "notify::visible", G_CALLBACK (st_widget_visible_notify), NULL);
g_signal_connect (actor, "notify::first-child", G_CALLBACK (st_widget_first_child_notify), NULL);
g_signal_connect (actor, "notify::last-child", G_CALLBACK (st_widget_last_child_notify), NULL);
priv->texture_file_changed_id = g_signal_connect (st_texture_cache_get_default (), "texture-file-changed",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]