mirror of
https://github.com/brl/mutter.git
synced 2024-11-24 17:10:40 -05:00
clutter/actor: Emit a signal when the stage-views an actor is on change
Add a new signal that's emitted when the stage views an actor being painted on have changed, "stage-views-changed". For example this signal can be helpful when tracking whether an actor is painted on multiple stage views or only one. Since we must clear the stage-views list when an actor leaves the stage (actors that aren't attached to a stage don't get notified about the stage views being changed/replaced), we also emit the new signal when an actor gets detached from the stage (otherwise there would be an edge case where no signal is emitted but it really should: An actor is visible on a stage view, then detached from the stage, and then attached again and immeditely moved outside the view). Also skip the comparison of the old stage-views list and the new one if nobody is listening to the signal to save some resources. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1196
This commit is contained in:
parent
675a97d58e
commit
18c792d6f8
@ -1020,6 +1020,7 @@ enum
|
|||||||
TRANSITIONS_COMPLETED,
|
TRANSITIONS_COMPLETED,
|
||||||
TOUCH_EVENT,
|
TOUCH_EVENT,
|
||||||
TRANSITION_STOPPED,
|
TRANSITION_STOPPED,
|
||||||
|
STAGE_VIEWS_CHANGED,
|
||||||
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
@ -4421,7 +4422,7 @@ clutter_actor_remove_child_internal (ClutterActor *self,
|
|||||||
* to the stage views, so make sure all the stage-views lists are
|
* to the stage views, so make sure all the stage-views lists are
|
||||||
* cleared as the child and its children leave the actor tree.
|
* cleared as the child and its children leave the actor tree.
|
||||||
*/
|
*/
|
||||||
if (clear_stage_views)
|
if (clear_stage_views && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
|
||||||
clutter_actor_clear_stage_views_recursive (child);
|
clutter_actor_clear_stage_views_recursive (child);
|
||||||
|
|
||||||
if (emit_parent_set && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
|
if (emit_parent_set && !CLUTTER_ACTOR_IN_DESTRUCTION (child))
|
||||||
@ -8634,6 +8635,27 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
|||||||
g_signal_set_va_marshaller (actor_signals[TOUCH_EVENT],
|
g_signal_set_va_marshaller (actor_signals[TOUCH_EVENT],
|
||||||
G_TYPE_FROM_CLASS (object_class),
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
_clutter_marshal_BOOLEAN__BOXEDv);
|
_clutter_marshal_BOOLEAN__BOXEDv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClutterActor::stage-views-changed:
|
||||||
|
* @actor: a #ClutterActor
|
||||||
|
*
|
||||||
|
* The ::stage-views-changed signal is emitted when the position or
|
||||||
|
* size an actor is being painted at have changed so that it's visible
|
||||||
|
* on different stage views.
|
||||||
|
*
|
||||||
|
* This signal is also emitted when the actor gets detached from the stage
|
||||||
|
* or when the views of the stage have been invalidated and will be
|
||||||
|
* replaced; it's not emitted when the actor gets hidden.
|
||||||
|
*/
|
||||||
|
actor_signals[STAGE_VIEWS_CHANGED] =
|
||||||
|
g_signal_new (I_("stage-views-changed"),
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -17540,10 +17562,15 @@ clear_stage_views_cb (ClutterActor *actor,
|
|||||||
int depth,
|
int depth,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
g_autoptr (GList) old_stage_views = NULL;
|
||||||
|
|
||||||
actor->priv->needs_update_stage_views = TRUE;
|
actor->priv->needs_update_stage_views = TRUE;
|
||||||
actor->priv->needs_compute_resource_scale = TRUE;
|
actor->priv->needs_compute_resource_scale = TRUE;
|
||||||
|
|
||||||
g_clear_pointer (&actor->priv->stage_views, g_list_free);
|
old_stage_views = g_steal_pointer (&actor->priv->stage_views);
|
||||||
|
|
||||||
|
if (old_stage_views)
|
||||||
|
g_signal_emit (actor, actor_signals[STAGE_VIEWS_CHANGED], 0);
|
||||||
|
|
||||||
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
|
return CLUTTER_ACTOR_TRAVERSE_VISIT_CONTINUE;
|
||||||
}
|
}
|
||||||
@ -17645,20 +17672,44 @@ clutter_actor_get_resource_scale (ClutterActor *self,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
sorted_lists_equal (GList *list_a,
|
||||||
|
GList *list_b)
|
||||||
|
{
|
||||||
|
GList *a, *b;
|
||||||
|
|
||||||
|
if (!list_a && !list_b)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
for (a = list_a, b = list_b;
|
||||||
|
a && b;
|
||||||
|
a = a->next, b = b->next)
|
||||||
|
{
|
||||||
|
if (a->data != b->data)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!a->next && !b->next)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_stage_views (ClutterActor *self)
|
update_stage_views (ClutterActor *self)
|
||||||
{
|
{
|
||||||
ClutterActorPrivate *priv = self->priv;
|
ClutterActorPrivate *priv = self->priv;
|
||||||
|
g_autoptr (GList) old_stage_views = NULL;
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
graphene_rect_t bounding_rect;
|
graphene_rect_t bounding_rect;
|
||||||
|
|
||||||
g_clear_pointer (&priv->stage_views, g_list_free);
|
old_stage_views = g_steal_pointer (&priv->stage_views);
|
||||||
|
|
||||||
if (priv->needs_allocation)
|
if (priv->needs_allocation)
|
||||||
{
|
{
|
||||||
g_warning ("Can't update stage views actor %s is on because it needs an "
|
g_warning ("Can't update stage views actor %s is on because it needs an "
|
||||||
"allocation.", _clutter_actor_get_debug_name (self));
|
"allocation.", _clutter_actor_get_debug_name (self));
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
|
stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
|
||||||
@ -17673,10 +17724,18 @@ update_stage_views (ClutterActor *self)
|
|||||||
|
|
||||||
if (bounding_rect.size.width == 0.0 ||
|
if (bounding_rect.size.width == 0.0 ||
|
||||||
bounding_rect.size.height == 0.0)
|
bounding_rect.size.height == 0.0)
|
||||||
return;
|
goto out;
|
||||||
|
|
||||||
priv->stage_views = clutter_stage_get_views_for_rect (stage,
|
priv->stage_views = clutter_stage_get_views_for_rect (stage,
|
||||||
&bounding_rect);
|
&bounding_rect);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (g_signal_has_handler_pending (self, actor_signals[STAGE_VIEWS_CHANGED],
|
||||||
|
0, TRUE))
|
||||||
|
{
|
||||||
|
if (!sorted_lists_equal (old_stage_views, priv->stage_views))
|
||||||
|
g_signal_emit (self, actor_signals[STAGE_VIEWS_CHANGED], 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user