background-content: Explicitly distinguish stage space from actor space

`meta_background_content_paint_content` was mixing two different
coordinate systems in `actor_pixel_rect`. It was initialized with
actor-local coordinates and then `if (self->clip_region)` would be
treated as stage coordinates. This worked because `self->clip_region`
was only non-NULL outside of the overview where both coordinate systems
were the same. So it always got the right answer, possibly by accident.

In order to enhance the function however we will need to know which
coordinate system we're working in, so now we make it explicit.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1363
This commit is contained in:
Daniel van Vugt 2020-07-09 16:52:07 +08:00 committed by Robert Mader
parent 0efecc1dc5
commit 30809665d8

View File

@ -501,41 +501,69 @@ meta_background_content_paint_content (ClutterContent *content,
{ {
MetaBackgroundContent *self = META_BACKGROUND_CONTENT (content); MetaBackgroundContent *self = META_BACKGROUND_CONTENT (content);
ClutterActorBox actor_box; ClutterActorBox actor_box;
cairo_rectangle_int_t actor_pixel_rect; cairo_rectangle_int_t rect_within_actor;
cairo_rectangle_int_t rect_within_stage;
cairo_region_t *region; cairo_region_t *region;
int i, n_rects; int i, n_rects;
float transformed_x, transformed_y, transformed_width, transformed_height;
gboolean untransformed;
if ((self->clip_region && cairo_region_is_empty (self->clip_region))) if ((self->clip_region && cairo_region_is_empty (self->clip_region)))
return; return;
clutter_actor_get_content_box (actor, &actor_box); clutter_actor_get_transformed_position (actor,
actor_pixel_rect.x = actor_box.x1; &transformed_x,
actor_pixel_rect.y = actor_box.y1; &transformed_y);
actor_pixel_rect.width = actor_box.x2 - actor_box.x1; rect_within_stage.x = floorf (transformed_x);
actor_pixel_rect.height = actor_box.y2 - actor_box.y1; rect_within_stage.y = floorf (transformed_y);
/* Now figure out what to actually paint */ clutter_actor_get_transformed_size (actor,
&transformed_width,
&transformed_height);
rect_within_stage.width = roundf (transformed_width);
rect_within_stage.height = roundf (transformed_height);
clutter_actor_get_content_box (actor, &actor_box);
rect_within_actor.x = actor_box.x1;
rect_within_actor.y = actor_box.y1;
rect_within_actor.width = actor_box.x2 - actor_box.x1;
rect_within_actor.height = actor_box.y2 - actor_box.y1;
untransformed =
rect_within_actor.x == rect_within_stage.x &&
rect_within_actor.y == rect_within_stage.y &&
rect_within_actor.width == rect_within_stage.width &&
rect_within_actor.height == rect_within_stage.height;
if (untransformed) /* actor and stage space are the same */
{
if (self->clip_region) if (self->clip_region)
{ {
region = cairo_region_copy (self->clip_region); region = cairo_region_copy (self->clip_region);
cairo_region_intersect_rectangle (region, &actor_pixel_rect); cairo_region_intersect_rectangle (region, &rect_within_stage);
} }
else else
{ {
region = cairo_region_create_rectangle (&actor_pixel_rect); region = cairo_region_create_rectangle (&rect_within_stage);
} }
if (self->unobscured_region) if (self->unobscured_region)
cairo_region_intersect (region, self->unobscured_region); cairo_region_intersect (region, self->unobscured_region);
}
else /* actor and stage space are different but we need actor space */
{
region = cairo_region_create_rectangle (&rect_within_actor);
}
/* region is now in actor space */
if (cairo_region_is_empty (region)) if (cairo_region_is_empty (region))
{ {
cairo_region_destroy (region); cairo_region_destroy (region);
return; return;
} }
setup_pipeline (self, actor, paint_context, &actor_pixel_rect); setup_pipeline (self, actor, paint_context, &rect_within_actor);
set_glsl_parameters (self, &actor_pixel_rect); set_glsl_parameters (self, &rect_within_actor);
/* Limit to how many separate rectangles we'll draw; beyond this just /* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */ * fall back and draw the whole thing */