[mutter] Report a correct paint volume for shadowed windows



commit 15f9590427650506a7098a1ba26ebc4bf8e6db6c
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Thu Nov 11 17:18:02 2010 -0500

    Report a correct paint volume for shadowed windows
    
    Since we paint shadows directly now rather than using a child actor
    in the ClutterGroup, we need to implement get_paint_volume() for
    Clutter 1.5.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=592382

 src/compositor/meta-window-actor.c |  100 ++++++++++++++++++++++++++++++------
 1 files changed, 84 insertions(+), 16 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 35227ca..ffb0160 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -9,6 +9,7 @@
 #include <X11/extensions/Xrender.h>
 
 #include <clutter/x11/clutter-x11.h>
+#include <gdk/gdk.h> /* for gdk_rectangle_union() */
 
 #include "display.h"
 #include "errors.h"
@@ -129,6 +130,10 @@ static void meta_window_actor_get_property (GObject      *object,
                                             GParamSpec   *pspec);
 
 static void meta_window_actor_paint (ClutterActor *actor);
+#if CLUTTER_CHECK_VERSION(1, 5, 2)
+static gboolean meta_window_actor_get_paint_volume (ClutterActor       *actor,
+                                                    ClutterPaintVolume *volume);
+#endif
 
 static void     meta_window_actor_detach     (MetaWindowActor *self);
 static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
@@ -202,6 +207,9 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
   object_class->constructed  = meta_window_actor_constructed;
 
   actor_class->paint = meta_window_actor_paint;
+#if CLUTTER_CHECK_VERSION(1, 5, 2)
+  actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
+#endif
 
   pspec = g_param_spec_object ("meta-window",
                                "MetaWindow",
@@ -619,10 +627,37 @@ meta_window_actor_get_shape_bounds (MetaWindowActor       *self,
 {
   MetaWindowActorPrivate *priv = self->priv;
 
-  if (priv->shaped)
+  /* We need to be defensive here because there are corner cases
+   * where getting the shape fails on a window being destroyed
+   * and similar.
+   */
+  if (priv->shaped && priv->shape_region)
     cairo_region_get_extents (priv->shape_region, bounds);
-  else
+  else if (priv->bounding_region)
     cairo_region_get_extents (priv->bounding_region, bounds);
+  else
+    bounds->x = bounds->y = bounds->width = bounds->height = 0;
+}
+
+static void
+meta_window_actor_get_shadow_bounds (MetaWindowActor       *self,
+                                     gboolean               appears_focused,
+                                     cairo_rectangle_int_t *bounds)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+  MetaShadow *shadow = appears_focused ? priv->focused_shadow : priv->unfocused_shadow;
+  cairo_rectangle_int_t shape_bounds;
+  MetaShadowParams params;
+
+  meta_window_actor_get_shape_bounds (self, &shape_bounds);
+  meta_window_actor_get_shadow_params (self, appears_focused, &params);
+
+  meta_shadow_get_bounds (shadow,
+                          params.x_offset + shape_bounds.x,
+                          params.y_offset + shape_bounds.y,
+                          shape_bounds.width,
+                          shape_bounds.height,
+                          bounds);
 }
 
 static void
@@ -656,6 +691,50 @@ meta_window_actor_paint (ClutterActor *actor)
   CLUTTER_ACTOR_CLASS (meta_window_actor_parent_class)->paint (actor);
 }
 
+#if CLUTTER_CHECK_VERSION(1, 5, 2)
+static gboolean
+meta_window_actor_get_paint_volume (ClutterActor       *actor,
+                                    ClutterPaintVolume *volume)
+{
+  MetaWindowActor *self = META_WINDOW_ACTOR (actor);
+  MetaWindowActorPrivate *priv = self->priv;
+  cairo_rectangle_int_t bounds;
+  gboolean appears_focused = meta_window_appears_focused (priv->window);
+  ClutterVertex origin;
+
+  /* The paint volume is computed before paint functions are called
+   * so our bounds might not be updated yet. Force an update. */
+  meta_window_actor_pre_paint (self);
+
+  meta_window_actor_get_shape_bounds (self, &bounds);
+
+  if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
+    {
+      cairo_rectangle_int_t shadow_bounds;
+
+      /* We could compute an full clip region as we do for the window
+       * texture, but the shadow is relatively cheap to draw, and
+       * a little more complex to clip, so we just catch the case where
+       * the shadow is completely obscured and doesn't need to be drawn
+       * at all.
+       */
+
+      meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
+      gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
+    }
+
+  origin.x = bounds.x;
+  origin.y = bounds.y;
+  origin.z = 0.0f;
+  clutter_paint_volume_set_origin (volume, &origin);
+
+  clutter_paint_volume_set_width (volume, bounds.width);
+  clutter_paint_volume_set_height (volume, bounds.height);
+
+  return TRUE;
+}
+#endif /* CLUTTER_CHECK_VERSION */
+
 static gboolean
 is_shaped (MetaDisplay *display, Window xwindow)
 {
@@ -1627,12 +1706,10 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
                                               cairo_region_t  *beneath_region)
 {
   MetaWindowActorPrivate *priv = self->priv;
+  gboolean appears_focused = meta_window_appears_focused (priv->window);
 
-  if (priv->focused_shadow)
+  if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
     {
-      gboolean appears_focused = meta_window_appears_focused (priv->window);
-      MetaShadowParams params;
-      cairo_rectangle_int_t shape_bounds;
       cairo_rectangle_int_t shadow_bounds;
       cairo_region_overlap_t overlap;
 
@@ -1642,16 +1719,7 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
        * the shadow is completely obscured and doesn't need to be drawn
        * at all.
        */
-      meta_window_actor_get_shape_bounds (self, &shape_bounds);
-      meta_window_actor_get_shadow_params (self, appears_focused, &params);
-
-      meta_shadow_get_bounds (appears_focused ? priv->focused_shadow : priv->unfocused_shadow,
-                              params.x_offset + shape_bounds.x,
-                              params.y_offset + shape_bounds.y,
-                              shape_bounds.width,
-                              shape_bounds.height,
-                              &shadow_bounds);
-
+      meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
       overlap = cairo_region_contains_rectangle (beneath_region, &shadow_bounds);
       priv->paint_shadow = overlap != CAIRO_REGION_OVERLAP_OUT;
     }



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