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
This commit is contained in:
Owen W. Taylor 2010-11-11 17:18:02 -05:00
parent 21a246eb42
commit 15f9590427

View File

@ -9,6 +9,7 @@
#include <X11/extensions/Xrender.h> #include <X11/extensions/Xrender.h>
#include <clutter/x11/clutter-x11.h> #include <clutter/x11/clutter-x11.h>
#include <gdk/gdk.h> /* for gdk_rectangle_union() */
#include "display.h" #include "display.h"
#include "errors.h" #include "errors.h"
@ -129,6 +130,10 @@ static void meta_window_actor_get_property (GObject *object,
GParamSpec *pspec); GParamSpec *pspec);
static void meta_window_actor_paint (ClutterActor *actor); 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 void meta_window_actor_detach (MetaWindowActor *self);
static gboolean meta_window_actor_has_shadow (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; object_class->constructed = meta_window_actor_constructed;
actor_class->paint = meta_window_actor_paint; 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", pspec = g_param_spec_object ("meta-window",
"MetaWindow", "MetaWindow",
@ -619,10 +627,37 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
{ {
MetaWindowActorPrivate *priv = self->priv; 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); cairo_region_get_extents (priv->shape_region, bounds);
else else if (priv->bounding_region)
cairo_region_get_extents (priv->bounding_region, bounds); 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 static void
@ -656,6 +691,50 @@ meta_window_actor_paint (ClutterActor *actor)
CLUTTER_ACTOR_CLASS (meta_window_actor_parent_class)->paint (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 static gboolean
is_shaped (MetaDisplay *display, Window xwindow) is_shaped (MetaDisplay *display, Window xwindow)
{ {
@ -1627,12 +1706,10 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region) cairo_region_t *beneath_region)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
if (priv->focused_shadow)
{
gboolean appears_focused = meta_window_appears_focused (priv->window); gboolean appears_focused = meta_window_appears_focused (priv->window);
MetaShadowParams params;
cairo_rectangle_int_t shape_bounds; if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
{
cairo_rectangle_int_t shadow_bounds; cairo_rectangle_int_t shadow_bounds;
cairo_region_overlap_t overlap; 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 * the shadow is completely obscured and doesn't need to be drawn
* at all. * at all.
*/ */
meta_window_actor_get_shape_bounds (self, &shape_bounds); meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_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);
overlap = cairo_region_contains_rectangle (beneath_region, &shadow_bounds); overlap = cairo_region_contains_rectangle (beneath_region, &shadow_bounds);
priv->paint_shadow = overlap != CAIRO_REGION_OVERLAP_OUT; priv->paint_shadow = overlap != CAIRO_REGION_OVERLAP_OUT;
} }