1
0
Fork 0

clutter/clone: Do not use global transformation for scaling clones

When cloning an actor we were applying a global scale to it, based on
the size of the clone itself and of the cloned actor.

This implied that the transformed size of the clone was not the one that
was set, but it was taking taking in account the actor scaling too.
So in practice we were scaling it twice.

While this had no visual implications it indeed was causing troubles
when a ClutterClone was reactive because in such case only the scaled
area of the scaled clone was considered reactive.

Assume you had an actor of 100x100 pixels, scaling it to a clone of
50x50 pixels:
 - The scale applied to the clone was 0.5
 - The transformed size of the clone was: 25x25 pixels
 - The clone was reactive only in that sub-area

To avoid this, never touch the clone transformation matrix, but only
transform it at paint time.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2959>

(cherry picked from commit 44c0c311ba)
This commit is contained in:
Marco Trevisan (Treviño) 2023-04-13 20:57:46 +02:00 committed by Jonas Ådahl
parent 3998f8a422
commit 7515316395

View file

@ -119,20 +119,6 @@ clutter_clone_get_preferred_height (ClutterActor *self,
natural_height_p); natural_height_p);
} }
static void
clutter_clone_apply_transform (ClutterActor *self,
graphene_matrix_t *matrix)
{
ClutterClonePrivate *priv =
clutter_clone_get_instance_private (CLUTTER_CLONE (self));
if (priv->clone_source)
graphene_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
CLUTTER_ACTOR_CLASS (clutter_clone_parent_class)->apply_transform (self,
matrix);
}
static void static void
clutter_clone_paint (ClutterActor *actor, clutter_clone_paint (ClutterActor *actor,
ClutterPaintContext *paint_context) ClutterPaintContext *paint_context)
@ -171,9 +157,22 @@ clutter_clone_paint (ClutterActor *actor,
*/ */
if (clutter_actor_is_realized (priv->clone_source)) if (clutter_actor_is_realized (priv->clone_source))
{ {
CoglFramebuffer *fb = NULL;
if (priv->x_scale != 1.0 || priv->y_scale != 1.0)
{
fb = clutter_paint_context_get_framebuffer (paint_context);
cogl_framebuffer_push_matrix (fb);
cogl_framebuffer_scale (fb, priv->x_scale, priv->y_scale, 1.0f);
}
_clutter_actor_push_clone_paint (); _clutter_actor_push_clone_paint ();
clutter_actor_paint (priv->clone_source, paint_context); clutter_actor_paint (priv->clone_source, paint_context);
_clutter_actor_pop_clone_paint (); _clutter_actor_pop_clone_paint ();
if (fb != NULL)
cogl_framebuffer_pop_matrix (fb);
} }
if (was_unmapped) if (was_unmapped)
@ -267,7 +266,7 @@ clutter_clone_allocate (ClutterActor *self,
{ {
priv->x_scale = x_scale; priv->x_scale = x_scale;
priv->y_scale = y_scale; priv->y_scale = y_scale;
clutter_actor_invalidate_transform (CLUTTER_ACTOR (self)); clutter_actor_queue_redraw (self);
} }
#if 0 #if 0
@ -342,7 +341,6 @@ clutter_clone_class_init (ClutterCloneClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
actor_class->apply_transform = clutter_clone_apply_transform;
actor_class->paint = clutter_clone_paint; actor_class->paint = clutter_clone_paint;
actor_class->get_paint_volume = clutter_clone_get_paint_volume; actor_class->get_paint_volume = clutter_clone_get_paint_volume;
actor_class->get_preferred_width = clutter_clone_get_preferred_width; actor_class->get_preferred_width = clutter_clone_get_preferred_width;