[mutter/wip/shape: 1/6] Refactor how shapes are done
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/shape: 1/6] Refactor how shapes are done
- Date: Tue, 27 Aug 2013 20:48:00 +0000 (UTC)
commit b42cd305923ab0ccc7fc7f0fa72db8d011cbebf7
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Fri Aug 23 23:30:47 2013 -0400
Refactor how shapes are done
src/compositor/meta-window-actor.c | 158 ++++++++++++++---------------------
src/core/display.c | 27 +------
src/core/window-private.h | 15 +++-
src/core/window-props.c | 2 +-
src/core/window.c | 141 +++++++++++++++++++++++++-------
5 files changed, 189 insertions(+), 154 deletions(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 1d90114..a32afed 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -10,7 +10,6 @@
#include <math.h>
-#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xrender.h>
@@ -400,7 +399,7 @@ meta_window_actor_constructed (GObject *object)
/* Start off with an empty region to maintain the invariant that
the shape region is always set */
- priv->shape_region = cairo_region_create();
+ priv->shape_region = cairo_region_create ();
}
static void
@@ -1332,7 +1331,7 @@ meta_window_actor_should_unredirect (MetaWindowActor *self)
if (priv->opacity != 0xff)
return FALSE;
- if (metaWindow->has_shape)
+ if (metaWindow->shape_region != NULL)
return FALSE;
if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
@@ -2220,105 +2219,58 @@ build_and_scan_frame_mask (MetaWindowActor *self,
}
static void
-check_needs_reshape (MetaWindowActor *self)
+meta_window_actor_update_shape_region (MetaWindowActor *self,
+ cairo_rectangle_int_t *client_area)
{
MetaWindowActorPrivate *priv = self->priv;
- MetaScreen *screen = priv->screen;
- MetaDisplay *display = meta_screen_get_display (screen);
- MetaFrameBorders borders;
cairo_region_t *region = NULL;
- cairo_rectangle_int_t client_area;
- gboolean needs_mask;
-
- if (!priv->mapped)
- return;
-
- if (!priv->needs_reshape)
- return;
- if (priv->shadow_shape != NULL)
+ if (priv->window->frame != NULL && priv->window->shape_region != NULL)
{
- meta_window_shape_unref (priv->shadow_shape);
- priv->shadow_shape = NULL;
+ region = cairo_region_copy (priv->window->shape_region);
+ cairo_region_translate (region, client_area->x, client_area->y);
+ }
+ else if (priv->window->shape_region != NULL)
+ {
+ region = cairo_region_reference (priv->window->shape_region);
}
-
- meta_frame_calc_borders (priv->window->frame, &borders);
-
- client_area.x = borders.total.left;
- client_area.y = borders.total.top;
- client_area.width = priv->window->rect.width;
- if (priv->window->shaded)
- client_area.height = 0;
else
- client_area.height = priv->window->rect.height;
+ {
+ /* If we don't have a shape on the server, that means that
+ * we have an implicit shape of one rectangle covering the
+ * entire window. */
+ region = cairo_region_create_rectangle (client_area);
+ }
meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), NULL);
+ if ((priv->window->shape_region != NULL) || (priv->window->frame != NULL))
+ build_and_scan_frame_mask (self, client_area, region);
+
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
- g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
+ priv->shape_region = region;
-#ifdef HAVE_SHAPE
- if (priv->window->has_shape)
+ if (priv->shadow_shape != NULL)
{
- /* Translate the set of XShape rectangles that we
- * get from the X server to a cairo_region. */
- Display *xdisplay = meta_display_get_xdisplay (display);
- XRectangle *rects;
- int n_rects, ordering;
-
- meta_error_trap_push (display);
- rects = XShapeGetRectangles (xdisplay,
- priv->window->xwindow,
- ShapeBounding,
- &n_rects,
- &ordering);
- meta_error_trap_pop (display);
-
- if (rects)
- {
- int i;
- cairo_rectangle_int_t *cairo_rects = g_new (cairo_rectangle_int_t, n_rects);
-
- for (i = 0; i < n_rects; i ++)
- {
- cairo_rects[i].x = rects[i].x + client_area.x;
- cairo_rects[i].y = rects[i].y + client_area.y;
- cairo_rects[i].width = rects[i].width;
- cairo_rects[i].height = rects[i].height;
- }
-
- XFree (rects);
- region = cairo_region_create_rectangles (cairo_rects, n_rects);
- g_free (cairo_rects);
- }
+ meta_window_shape_unref (priv->shadow_shape);
+ priv->shadow_shape = NULL;
}
-#endif
- needs_mask = (region != NULL) || (priv->window->frame != NULL);
+ meta_window_actor_invalidate_shadow (self);
+}
- if (region != NULL)
- {
- /* The shape we get back from the client may have coordinates
- * outside of the frame. The X SHAPE Extension requires that
- * the overall shape the client provides never exceeds the
- * "bounding rectangle" of the window -- the shape that the
- * window would have gotten if it was unshaped. In our case,
- * this is simply the client area.
- */
- cairo_region_intersect_rectangle (region, &client_area);
- }
- else
- {
- /* If we don't have a shape on the server, that means that
- * we have an implicit shape of one rectangle covering the
- * entire window. */
- region = cairo_region_create_rectangle (&client_area);
- }
+static void
+meta_window_actor_update_opaque_region (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
- /* The region at this point should be constrained to the
- * bounds of the client rectangle. */
+ g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
if (priv->argb32 && priv->window->opaque_region != NULL)
{
+ MetaFrameBorders borders;
+
+ meta_frame_calc_borders (priv->window->frame, &borders);
+
/* The opaque region is defined to be a part of the
* window which ARGB32 will always paint with opaque
* pixels. For these regions, we want to avoid painting
@@ -2330,24 +2282,40 @@ check_needs_reshape (MetaWindowActor *self)
* case, graphical glitches will occur.
*/
priv->opaque_region = cairo_region_copy (priv->window->opaque_region);
- cairo_region_translate (priv->opaque_region, client_area.x, client_area.y);
- cairo_region_intersect (priv->opaque_region, region);
+ cairo_region_translate (priv->opaque_region, borders.total.left, borders.total.top);
+ cairo_region_intersect (priv->opaque_region, priv->shape_region);
}
else if (priv->argb32)
priv->opaque_region = NULL;
else
- priv->opaque_region = cairo_region_reference (region);
+ priv->opaque_region = cairo_region_reference (priv->shape_region);
+}
- if (needs_mask)
- {
- /* This takes the region, generates a mask using GTK+
- * and scans the mask looking for all opaque pixels,
- * adding it to region.
- */
- build_and_scan_frame_mask (self, &client_area, region);
- }
+static void
+check_needs_reshape (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+ MetaFrameBorders borders;
+ cairo_rectangle_int_t client_area;
- priv->shape_region = region;
+ if (!priv->mapped)
+ return;
+
+ if (!priv->needs_reshape)
+ return;
+
+ meta_frame_calc_borders (priv->window->frame, &borders);
+
+ client_area.x = borders.total.left;
+ client_area.y = borders.total.top;
+ client_area.width = priv->window->rect.width;
+ if (priv->window->shaded)
+ client_area.height = 0;
+ else
+ client_area.height = priv->window->rect.height;
+
+ meta_window_actor_update_shape_region (self, &client_area);
+ meta_window_actor_update_opaque_region (self);
priv->needs_reshape = FALSE;
meta_window_actor_invalidate_shadow (self);
diff --git a/src/core/display.c b/src/core/display.c
index f412c66..3f3a45f 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2283,32 +2283,7 @@ event_callback (XEvent *event,
XShapeEvent *sev = (XShapeEvent*) event;
if (sev->kind == ShapeBounding)
- {
- if (sev->shaped && !window->has_shape)
- {
- window->has_shape = TRUE;
- meta_topic (META_DEBUG_SHAPES,
- "Window %s now has a shape\n",
- window->desc);
- }
- else if (!sev->shaped && window->has_shape)
- {
- window->has_shape = FALSE;
- meta_topic (META_DEBUG_SHAPES,
- "Window %s no longer has a shape\n",
- window->desc);
- }
- else
- {
- meta_topic (META_DEBUG_SHAPES,
- "Window %s shape changed\n",
- window->desc);
- }
-
- if (display->compositor)
- meta_compositor_window_shape_changed (display->compositor,
- window);
- }
+ meta_window_update_shape_region_x11 (window);
}
else
{
diff --git a/src/core/window-private.h b/src/core/window-private.h
index e7255be..7572632 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -325,9 +325,6 @@ struct _MetaWindow
guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */
guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
- /* has a shape mask */
- guint has_shape : 1;
-
/* icon props have changed */
guint need_reread_icon : 1;
@@ -349,6 +346,9 @@ struct _MetaWindow
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
+ /* if non-NULL, the bounding shape region of the window */
+ cairo_region_t *shape_region;
+
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
cairo_region_t *opaque_region;
@@ -665,7 +665,6 @@ void meta_window_update_icon_now (MetaWindow *window);
void meta_window_update_role (MetaWindow *window);
void meta_window_update_net_wm_type (MetaWindow *window);
-void meta_window_update_opaque_region (MetaWindow *window);
void meta_window_update_for_monitors_changed (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window);
@@ -679,4 +678,12 @@ void meta_window_compute_tile_match (MetaWindow *window);
gboolean meta_window_updates_are_frozen (MetaWindow *window);
+void meta_window_set_opaque_region (MetaWindow *window,
+ cairo_region_t *region);
+void meta_window_update_opaque_region_x11 (MetaWindow *window);
+
+void meta_window_set_shape_region (MetaWindow *window,
+ cairo_region_t *region);
+void meta_window_update_shape_region_x11 (MetaWindow *window);
+
#endif
diff --git a/src/core/window-props.c b/src/core/window-props.c
index adbfe59..13ee3bb 100644
--- a/src/core/window-props.c
+++ b/src/core/window-props.c
@@ -565,7 +565,7 @@ reload_opaque_region (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
- meta_window_update_opaque_region (window);
+ meta_window_update_opaque_region_x11 (window);
}
static void
diff --git a/src/core/window.c b/src/core/window.c
index b109ec3..9b49cfb 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -825,7 +825,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
gulong existing_wm_state;
gulong event_mask;
MetaMoveResizeFlags flags;
- gboolean has_shape;
MetaScreen *screen;
g_assert (attrs != NULL);
@@ -959,29 +958,9 @@ meta_window_new_with_attrs (MetaDisplay *display,
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
}
- has_shape = FALSE;
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (display))
- {
- int x_bounding, y_bounding, x_clip, y_clip;
- unsigned w_bounding, h_bounding, w_clip, h_clip;
- int bounding_shaped, clip_shaped;
-
- XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask);
-
- XShapeQueryExtents (display->xdisplay, xwindow,
- &bounding_shaped, &x_bounding, &y_bounding,
- &w_bounding, &h_bounding,
- &clip_shaped, &x_clip, &y_clip,
- &w_clip, &h_clip);
-
- has_shape = bounding_shaped != FALSE;
-
- meta_topic (META_DEBUG_SHAPES,
- "Window has_shape = %d extents %d,%d %u x %u\n",
- has_shape, x_bounding, y_bounding,
- w_bounding, h_bounding);
- }
+ XShapeSelectInput (display->xdisplay, xwindow, ShapeNotifyMask);
#endif
/* Get rid of any borders */
@@ -1041,8 +1020,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
/* avoid tons of stack updates */
meta_stack_freeze (window->screen->stack);
- window->has_shape = has_shape;
-
window->rect.x = attrs->x;
window->rect.y = attrs->y;
window->rect.width = attrs->width;
@@ -1213,6 +1190,8 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_display_register_x_window (display, &window->xwindow, window);
+ meta_window_update_shape_region_x11 (window);
+
/* Assign this #MetaWindow a sequence number which can be used
* for sorting.
*/
@@ -7637,14 +7616,25 @@ meta_window_update_net_wm_type (MetaWindow *window)
}
void
-meta_window_update_opaque_region (MetaWindow *window)
+meta_window_set_opaque_region (MetaWindow *window,
+ cairo_region_t *region)
+{
+ g_clear_pointer (&window->opaque_region, cairo_region_destroy);
+
+ if (region != NULL)
+ window->opaque_region = cairo_region_reference (region);
+
+ if (window->display->compositor)
+ meta_compositor_window_shape_changed (window->display->compositor, window);
+}
+
+void
+meta_window_update_opaque_region_x11 (MetaWindow *window)
{
cairo_region_t *opaque_region = NULL;
gulong *region = NULL;
int nitems;
- g_clear_pointer (&window->opaque_region, cairo_region_destroy);
-
if (meta_prop_get_cardinal_list (window->display,
window->xwindow,
window->display->atom__NET_WM_OPAQUE_REGION,
@@ -7687,13 +7677,108 @@ meta_window_update_opaque_region (MetaWindow *window)
}
out:
- window->opaque_region = opaque_region;
meta_XFree (region);
+ meta_window_set_opaque_region (window, opaque_region);
+ cairo_region_destroy (opaque_region);
+}
+
+static cairo_region_t *
+region_create_from_x_rectangles (const XRectangle *rects,
+ int n_rects)
+{
+ int i;
+ cairo_rectangle_int_t *cairo_rects = g_newa (cairo_rectangle_int_t, n_rects);
+
+ for (i = 0; i < n_rects; i ++)
+ {
+ cairo_rects[i].x = rects[i].x;
+ cairo_rects[i].y = rects[i].y;
+ cairo_rects[i].width = rects[i].width;
+ cairo_rects[i].height = rects[i].height;
+ }
+
+ return cairo_region_create_rectangles (cairo_rects, n_rects);
+}
+
+void
+meta_window_set_shape_region (MetaWindow *window,
+ cairo_region_t *region)
+{
+ g_clear_pointer (&window->shape_region, cairo_region_destroy);
+
+ if (region != NULL)
+ window->shape_region = cairo_region_reference (region);
+
if (window->display->compositor)
meta_compositor_window_shape_changed (window->display->compositor, window);
}
+void
+meta_window_update_shape_region_x11 (MetaWindow *window)
+{
+ cairo_region_t *region = NULL;
+
+#ifdef HAVE_SHAPE
+ if (META_DISPLAY_HAS_SHAPE (window->display))
+ {
+ /* Translate the set of XShape rectangles that we
+ * get from the X server to a cairo_region. */
+ XRectangle *rects = NULL;
+ int n_rects, ordering;
+
+ int x_bounding, y_bounding, x_clip, y_clip;
+ unsigned w_bounding, h_bounding, w_clip, h_clip;
+ int bounding_shaped, clip_shaped;
+
+ meta_error_trap_push (window->display);
+ XShapeQueryExtents (window->display->xdisplay, window->xwindow,
+ &bounding_shaped, &x_bounding, &y_bounding,
+ &w_bounding, &h_bounding,
+ &clip_shaped, &x_clip, &y_clip,
+ &w_clip, &h_clip);
+
+ if (bounding_shaped)
+ {
+ rects = XShapeGetRectangles (window->display->xdisplay,
+ window->xwindow,
+ ShapeBounding,
+ &n_rects,
+ &ordering);
+ }
+ meta_error_trap_pop (window->display);
+
+ if (rects)
+ {
+ region = region_create_from_x_rectangles (rects, n_rects);
+ XFree (rects);
+ }
+ }
+#endif
+
+ if (region != NULL)
+ {
+ cairo_rectangle_int_t client_area;
+
+ client_area.x = 0;
+ client_area.y = 0;
+ client_area.width = window->rect.width;
+ client_area.height = window->rect.height;
+
+ /* The shape we get back from the client may have coordinates
+ * outside of the frame. The X SHAPE Extension requires that
+ * the overall shape the client provides never exceeds the
+ * "bounding rectangle" of the window -- the shape that the
+ * window would have gotten if it was unshaped. In our case,
+ * this is simply the client area.
+ */
+ cairo_region_intersect_rectangle (region, &client_area);
+ }
+
+ meta_window_set_shape_region (window, region);
+ cairo_region_destroy (region);
+}
+
static void
redraw_icon (MetaWindow *window)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]