Track the shape of the client window directly
Since we're not setting the frame's output shape any more, it doesn't make sense to calculate the output shape based on the frame window. Instead, track the client window directly and calculate the output shape based on that. https://bugzilla.gnome.org/show_bug.cgi?id=644930
This commit is contained in:
parent
65e1b416ef
commit
7e0a56fb80
5 changed files with 66 additions and 102 deletions
|
@ -109,28 +109,6 @@ process_damage (MetaCompositor *compositor,
|
|||
meta_window_actor_process_damage (window_actor, event);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
static void
|
||||
process_shape (MetaCompositor *compositor,
|
||||
XShapeEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (window_actor == NULL)
|
||||
return;
|
||||
|
||||
if (event->kind == ShapeBounding)
|
||||
{
|
||||
meta_window_actor_update_shape (window_actor, event->shaped);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
process_property_notify (MetaCompositor *compositor,
|
||||
XPropertyEvent *event,
|
||||
|
@ -674,6 +652,16 @@ is_grabbed_event (XEvent *event)
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_update_shape (window_actor);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_compositor_process_event: (skip)
|
||||
*
|
||||
|
@ -753,13 +741,6 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
|||
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
|
||||
process_damage (compositor, (XDamageNotifyEvent *) event, window);
|
||||
}
|
||||
#ifdef HAVE_SHAPE
|
||||
else if (event->type == meta_display_get_shape_event_base (compositor->display) + ShapeNotify)
|
||||
{
|
||||
DEBUG_TRACE ("meta_compositor_process_event (process_shape)\n");
|
||||
process_shape (compositor, (XShapeEvent *) event, window);
|
||||
}
|
||||
#endif /* HAVE_SHAPE */
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,8 +33,7 @@ void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
|
|||
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
|
||||
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
||||
void meta_window_actor_update_shape (MetaWindowActor *self,
|
||||
gboolean shaped);
|
||||
void meta_window_actor_update_shape (MetaWindowActor *self);
|
||||
void meta_window_actor_update_opacity (MetaWindowActor *self);
|
||||
void meta_window_actor_mapped (MetaWindowActor *self);
|
||||
void meta_window_actor_unmapped (MetaWindowActor *self);
|
||||
|
|
|
@ -96,7 +96,6 @@ struct _MetaWindowActorPrivate
|
|||
|
||||
guint visible : 1;
|
||||
guint mapped : 1;
|
||||
guint shaped : 1;
|
||||
guint argb32 : 1;
|
||||
guint disposed : 1;
|
||||
guint redecorating : 1;
|
||||
|
@ -156,8 +155,6 @@ static void meta_window_actor_clear_shape_region (MetaWindowActor *self);
|
|||
static void meta_window_actor_clear_bounding_region (MetaWindowActor *self);
|
||||
static void meta_window_actor_clear_shadow_clip (MetaWindowActor *self);
|
||||
|
||||
static gboolean is_shaped (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
/*
|
||||
* Register GType wrapper for XWindowAttributes, so we do not have to
|
||||
* query window attributes in the MetaWindowActor constructor but can pass
|
||||
|
@ -392,14 +389,6 @@ meta_window_actor_constructed (GObject *object)
|
|||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
XRenderPictFormat *format;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
/* Listen for ShapeNotify events on the window */
|
||||
if (meta_display_has_shape (display))
|
||||
XShapeSelectInput (xdisplay, xwindow, ShapeNotifyMask);
|
||||
#endif
|
||||
|
||||
priv->shaped = is_shaped (display, xwindow);
|
||||
|
||||
if (priv->attrs.class == InputOnly)
|
||||
priv->damage = None;
|
||||
else
|
||||
|
@ -441,7 +430,7 @@ meta_window_actor_constructed (GObject *object)
|
|||
}
|
||||
|
||||
meta_window_actor_update_opacity (self);
|
||||
meta_window_actor_update_shape (self, priv->shaped);
|
||||
meta_window_actor_update_shape (self);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -671,7 +660,7 @@ meta_window_actor_get_shape_bounds (MetaWindowActor *self,
|
|||
* where getting the shape fails on a window being destroyed
|
||||
* and similar.
|
||||
*/
|
||||
if (priv->shaped && priv->shape_region)
|
||||
if (priv->shape_region)
|
||||
cairo_region_get_extents (priv->shape_region, bounds);
|
||||
else if (priv->bounding_region)
|
||||
cairo_region_get_extents (priv->bounding_region, bounds);
|
||||
|
@ -809,25 +798,6 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_shaped (MetaDisplay *display, Window xwindow)
|
||||
{
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
gint xws, yws, xbs, ybs;
|
||||
guint wws, hws, wbs, hbs;
|
||||
gint bounding_shaped, clip_shaped;
|
||||
|
||||
if (meta_display_has_shape (display))
|
||||
{
|
||||
XShapeQueryExtents (xdisplay, xwindow, &bounding_shaped,
|
||||
&xws, &yws, &wws, &hws, &clip_shaped,
|
||||
&xbs, &ybs, &wbs, &hbs);
|
||||
return (bounding_shaped != 0);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_window_actor_has_shadow (MetaWindowActor *self)
|
||||
{
|
||||
|
@ -1679,22 +1649,7 @@ meta_window_actor_update_bounding_region (MetaWindowActor *self,
|
|||
|
||||
priv->bounding_region = cairo_region_create_rectangle (&bounding_rectangle);
|
||||
|
||||
if (priv->shaped)
|
||||
{
|
||||
/* If we're shaped, the implicit shape region clipping we need to do needs
|
||||
* to be updated.
|
||||
*/
|
||||
meta_window_actor_update_shape (self, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* When we're shaped, we use the shape region to generate the shadow; the shape
|
||||
* region only changes when we get ShapeNotify event; but for unshaped windows
|
||||
* we generate the shadow from the bounding region, so we need to recompute
|
||||
* the shadow when the size changes.
|
||||
*/
|
||||
meta_window_actor_invalidate_shadow (self);
|
||||
}
|
||||
meta_window_actor_update_shape (self);
|
||||
|
||||
g_signal_emit (self, signals[SIZE_CHANGED], 0);
|
||||
}
|
||||
|
@ -1743,7 +1698,7 @@ meta_window_actor_get_obscured_region (MetaWindowActor *self)
|
|||
|
||||
if (!priv->argb32 && priv->opacity == 0xff && priv->back_pixmap)
|
||||
{
|
||||
if (priv->shaped)
|
||||
if (priv->shape_region)
|
||||
return priv->shape_region;
|
||||
else
|
||||
return priv->bounding_region;
|
||||
|
@ -1793,16 +1748,10 @@ meta_window_actor_set_visible_region (MetaWindowActor *self,
|
|||
/* Get the area of the window texture that would be drawn if
|
||||
* we weren't obscured at all
|
||||
*/
|
||||
if (priv->shaped)
|
||||
{
|
||||
if (priv->shape_region)
|
||||
texture_clip_region = cairo_region_copy (priv->shape_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->bounding_region)
|
||||
texture_clip_region = cairo_region_copy (priv->bounding_region);
|
||||
}
|
||||
if (priv->shape_region)
|
||||
texture_clip_region = cairo_region_copy (priv->shape_region);
|
||||
else if (priv->bounding_region)
|
||||
texture_clip_region = cairo_region_copy (priv->bounding_region);
|
||||
|
||||
if (!texture_clip_region)
|
||||
texture_clip_region = cairo_region_create ();
|
||||
|
@ -2014,7 +1963,7 @@ check_needs_shadow (MetaWindowActor *self)
|
|||
{
|
||||
if (priv->shadow_shape == NULL)
|
||||
{
|
||||
if (priv->shaped && priv->shape_region)
|
||||
if (priv->shape_region)
|
||||
priv->shadow_shape = meta_window_shape_new (priv->shape_region);
|
||||
else if (priv->bounding_region)
|
||||
priv->shadow_shape = meta_window_shape_new (priv->bounding_region);
|
||||
|
@ -2106,18 +2055,51 @@ check_needs_reshape (MetaWindowActor *self)
|
|||
if (!priv->needs_reshape)
|
||||
return;
|
||||
|
||||
region = NULL;
|
||||
meta_shaped_texture_set_shape_region (META_SHAPED_TEXTURE (priv->actor), NULL);
|
||||
meta_window_actor_clear_shape_region (self);
|
||||
|
||||
region = meta_window_get_frame_bounds (priv->window);
|
||||
if (region != NULL)
|
||||
{
|
||||
/* This returns the window's internal frame bounds region,
|
||||
* so we need to copy it because we modify it below. */
|
||||
region = cairo_region_copy (region);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we have no region, we have no frame. We have no frame,
|
||||
* so just use the bounding region instead */
|
||||
region = cairo_region_copy (priv->bounding_region);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if (priv->shaped)
|
||||
if (priv->window->has_shape)
|
||||
{
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
XRectangle *rects;
|
||||
int n_rects, ordering;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
client_area.width = priv->window->rect.width;
|
||||
client_area.height = priv->window->rect.height;
|
||||
|
||||
if (priv->window->frame)
|
||||
{
|
||||
client_area.x = priv->window->frame->child_x;
|
||||
client_area.y = priv->window->frame->child_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
client_area.x = 0;
|
||||
client_area.y = 0;
|
||||
}
|
||||
|
||||
/* Punch out client area. */
|
||||
cairo_region_subtract_rectangle (region, &client_area);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
rects = XShapeGetRectangles (xdisplay,
|
||||
priv->xwindow,
|
||||
priv->window->xwindow,
|
||||
ShapeBounding,
|
||||
&n_rects,
|
||||
&ordering);
|
||||
|
@ -2126,13 +2108,10 @@ check_needs_reshape (MetaWindowActor *self)
|
|||
if (rects)
|
||||
{
|
||||
int i;
|
||||
|
||||
region = cairo_region_create ();
|
||||
|
||||
for (i = 0; i < n_rects; i ++)
|
||||
{
|
||||
cairo_rectangle_int_t rect = { rects[i].x,
|
||||
rects[i].y,
|
||||
cairo_rectangle_int_t rect = { rects[i].x + client_area.x,
|
||||
rects[i].y + client_area.y,
|
||||
rects[i].width,
|
||||
rects[i].height };
|
||||
cairo_region_union_rectangle (region, &rect);
|
||||
|
@ -2154,12 +2133,10 @@ check_needs_reshape (MetaWindowActor *self)
|
|||
}
|
||||
|
||||
void
|
||||
meta_window_actor_update_shape (MetaWindowActor *self,
|
||||
gboolean shaped)
|
||||
meta_window_actor_update_shape (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
priv->shaped = shaped;
|
||||
priv->needs_reshape = TRUE;
|
||||
if (priv->shadow_shape != NULL)
|
||||
{
|
||||
|
|
|
@ -1696,6 +1696,10 @@ event_callback (XEvent *event,
|
|||
"Window %s shape changed\n",
|
||||
window->desc);
|
||||
}
|
||||
|
||||
if (display->compositor)
|
||||
meta_compositor_window_shape_changed (display->compositor,
|
||||
window);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -64,6 +64,9 @@ void meta_compositor_manage_screen (MetaCompositor *compositor,
|
|||
void meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
||||
MetaScreen *screen);
|
||||
|
||||
void meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
gboolean meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window);
|
||||
|
|
Loading…
Reference in a new issue