[mutter] background-content: Explicitly distinguish stage space from actor space



commit 30809665d84ac1a74c8787219579e65b5d1e612f
Author: Daniel van Vugt <daniel van vugt canonical com>
Date:   Thu Jul 9 16:52:07 2020 +0800

    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

 src/compositor/meta-background-content.c | 62 +++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 17 deletions(-)
---
diff --git a/src/compositor/meta-background-content.c b/src/compositor/meta-background-content.c
index 8825445de5..1ccec1d867 100644
--- a/src/compositor/meta-background-content.c
+++ b/src/compositor/meta-background-content.c
@@ -501,41 +501,69 @@ meta_background_content_paint_content (ClutterContent      *content,
 {
   MetaBackgroundContent *self = META_BACKGROUND_CONTENT (content);
   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;
   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)))
     return;
 
-  clutter_actor_get_content_box (actor, &actor_box);
-  actor_pixel_rect.x = actor_box.x1;
-  actor_pixel_rect.y = actor_box.y1;
-  actor_pixel_rect.width = actor_box.x2 - actor_box.x1;
-  actor_pixel_rect.height = actor_box.y2 - actor_box.y1;
+  clutter_actor_get_transformed_position (actor,
+                                          &transformed_x,
+                                          &transformed_y);
+  rect_within_stage.x = floorf (transformed_x);
+  rect_within_stage.y = floorf (transformed_y);
+
+  clutter_actor_get_transformed_size (actor,
+                                      &transformed_width,
+                                      &transformed_height);
+  rect_within_stage.width = roundf (transformed_width);
+  rect_within_stage.height = roundf (transformed_height);
 
-  /* Now figure out what to actually paint */
-  if (self->clip_region)
+  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 */
     {
-      region = cairo_region_copy (self->clip_region);
-      cairo_region_intersect_rectangle (region, &actor_pixel_rect);
+      if (self->clip_region)
+        {
+          region = cairo_region_copy (self->clip_region);
+          cairo_region_intersect_rectangle (region, &rect_within_stage);
+        }
+      else
+        {
+          region = cairo_region_create_rectangle (&rect_within_stage);
+        }
+
+      if (self->unobscured_region)
+        cairo_region_intersect (region, self->unobscured_region);
     }
-  else
+  else /* actor and stage space are different but we need actor space */
     {
-      region = cairo_region_create_rectangle (&actor_pixel_rect);
+      region = cairo_region_create_rectangle (&rect_within_actor);
     }
 
-  if (self->unobscured_region)
-    cairo_region_intersect (region, self->unobscured_region);
-
+  /* region is now in actor space */
   if (cairo_region_is_empty (region))
     {
       cairo_region_destroy (region);
       return;
     }
 
-  setup_pipeline (self, actor, paint_context, &actor_pixel_rect);
-  set_glsl_parameters (self, &actor_pixel_rect);
+  setup_pipeline (self, actor, paint_context, &rect_within_actor);
+  set_glsl_parameters (self, &rect_within_actor);
 
   /* Limit to how many separate rectangles we'll draw; beyond this just
    * fall back and draw the whole thing */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]