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
This commit is contained in:
parent
5f4e0e5ff8
commit
4d0a742d64
@ -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,30 +1584,78 @@ 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_visible_notify (StWidget *widget,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *actor = CLUTTER_ACTOR (widget);
|
||||
ClutterActor *parent = clutter_actor_get_parent (actor);
|
||||
|
||||
if (parent == NULL || !ST_IS_WIDGET (parent))
|
||||
return;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
new_first = find_nearest_visible_forward (CLUTTER_ACTOR (widget));
|
||||
st_widget_set_first_visible_child (ST_WIDGET (parent), new_first);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
st_widget_first_child_notify (StWidget *widget,
|
||||
GParamSpec *pspec,
|
||||
gpointer data)
|
||||
{
|
||||
StWidgetPrivate *priv = st_widget_get_instance_private (widget);
|
||||
ClutterActor *first_child;
|
||||
|
||||
if (priv->prev_first_child != NULL)
|
||||
{
|
||||
st_widget_remove_style_pseudo_class (priv->prev_first_child, "first-child");
|
||||
g_clear_object (&priv->prev_first_child);
|
||||
}
|
||||
|
||||
first_child = clutter_actor_get_first_child (CLUTTER_ACTOR (widget));
|
||||
|
||||
if (first_child == NULL)
|
||||
return;
|
||||
|
||||
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));
|
||||
}
|
||||
st_widget_set_first_visible_child (widget, find_nearest_visible_forward (first_child));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1560,25 +1663,10 @@ 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",
|
||||
|
Loading…
Reference in New Issue
Block a user