[mutter/wip/wayland-opaque: 4/7] wayland: Add support for set_opaque_region / set_input_region
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland-opaque: 4/7] wayland: Add support for set_opaque_region / set_input_region
- Date: Wed, 28 Aug 2013 17:25:09 +0000 (UTC)
commit 284b497b4c5b560bf49e8cc2769972265c61887a
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Fri Aug 23 22:20:49 2013 -0400
wayland: Add support for set_opaque_region / set_input_region
src/compositor/compositor.c | 4 +-
src/compositor/meta-window-actor.c | 237 ++++++++++-----------------------
src/compositor/meta-window-group.c | 10 +--
src/core/display.c | 54 +-------
src/core/window-private.h | 24 +++-
src/core/window-props.c | 2 +-
src/core/window.c | 261 +++++++++++++++++++++++++++---------
src/meta/compositor.h | 4 +-
src/wayland/meta-wayland.c | 28 +++-
9 files changed, 316 insertions(+), 308 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 5565dd0..2156452 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -930,8 +930,8 @@ is_grabbed_event (MetaDisplay *display,
}
void
-meta_compositor_window_x11_shape_changed (MetaCompositor *compositor,
- MetaWindow *window)
+meta_compositor_window_shape_changed (MetaCompositor *compositor,
+ MetaWindow *window)
{
MetaWindowActor *window_actor;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 4999602..dadbb73 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>
@@ -71,7 +70,7 @@ struct _MetaWindowActorPrivate
/* A region that matches the shape of the window, including frame bounds */
cairo_region_t *shape_region;
/* If the window has an input shape, a region that matches the shape */
- cairo_region_t *input_shape_region;
+ cairo_region_t *input_region;
/* The opaque region, from _NET_WM_OPAQUE_REGION, intersected with
* the shape region. */
cairo_region_t *opaque_region;
@@ -407,8 +406,8 @@ meta_window_actor_constructed (GObject *object)
/* Start off with empty regions to maintain the invariant that
these regions are always set */
- priv->shape_region = cairo_region_create();
- priv->input_shape_region = cairo_region_create();
+ priv->shape_region = cairo_region_create ();
+ priv->input_region = cairo_region_create ();
}
static void
@@ -438,7 +437,7 @@ meta_window_actor_dispose (GObject *object)
}
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
- g_clear_pointer (&priv->input_shape_region, cairo_region_destroy);
+ g_clear_pointer (&priv->input_region, cairo_region_destroy);
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
@@ -1260,7 +1259,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))
@@ -2171,33 +2170,36 @@ build_and_scan_frame_mask (MetaWindowActor *self,
g_free (mask_data);
}
-static cairo_region_t *
-region_create_from_x_rectangles (const XRectangle *rects,
- int n_rects,
- int dx,
- int dy)
+static void
+meta_window_actor_update_shape_region (MetaWindowActor *self,
+ cairo_rectangle_int_t *client_area)
{
- int i;
- cairo_rectangle_int_t *cairo_rects = g_newa (cairo_rectangle_int_t, n_rects);
+ MetaWindowActorPrivate *priv = self->priv;
+ cairo_region_t *region = NULL;
- for (i = 0; i < n_rects; i ++)
+ if (priv->window->frame != NULL && priv->window->shape_region != 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)
{
- cairo_rects[i].x = rects[i].x + dx;
- cairo_rects[i].y = rects[i].y + dy;
- cairo_rects[i].width = rects[i].width;
- cairo_rects[i].height = rects[i].height;
+ region = cairo_region_reference (priv->window->shape_region);
+ }
+ 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);
}
- return cairo_region_create_rectangles (cairo_rects, n_rects);
-}
+ 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);
-static void
-meta_window_actor_update_x11_shape_region (MetaWindowActor *self,
- cairo_rectangle_int_t *client_area)
-{
- MetaWindowActorPrivate *priv = self->priv;
- cairo_region_t *region = NULL;
- gboolean needs_mask;
+ g_clear_pointer (&priv->shape_region, cairo_region_destroy);
+ priv->shape_region = region;
if (priv->shadow_shape != NULL)
{
@@ -2205,51 +2207,31 @@ meta_window_actor_update_x11_shape_region (MetaWindowActor *self,
priv->shadow_shape = NULL;
}
- meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), NULL);
- g_clear_pointer (&priv->shape_region, cairo_region_destroy);
- g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
+ meta_window_actor_invalidate_shadow (self);
+}
+
+static void
+meta_window_actor_update_input_region (MetaWindowActor *self,
+ cairo_rectangle_int_t *client_area)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+ MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor);
+ cairo_region_t *region = NULL;
-#ifdef HAVE_SHAPE
- if (priv->window->has_shape)
+ if (priv->window->frame != NULL && priv->window->shape_region != NULL)
{
- /* Translate the set of XShape rectangles that we
- * get from the X server to a cairo_region. */
- MetaScreen *screen = priv->screen;
- MetaDisplay *display = meta_screen_get_display (screen);
- Display *xdisplay = meta_display_get_xdisplay (display);
- XRectangle *rects;
- int n_rects, ordering;
+ cairo_region_t *client_region = cairo_region_copy (priv->window->input_region);
- meta_error_trap_push (display);
- rects = XShapeGetRectangles (xdisplay,
- priv->window->xwindow,
- ShapeBounding,
- &n_rects,
- &ordering);
- meta_error_trap_pop (display);
+ region = meta_frame_get_frame_bounds (priv->window->frame);
- if (rects)
- {
- region = region_create_from_x_rectangles (rects, n_rects,
- client_area->x,
- client_area->y);
- XFree (rects);
- }
+ cairo_region_subtract_rectangle (region, client_area);
+ cairo_region_translate (client_region, client_area->x, client_area->y);
+ cairo_region_union (region, client_region);
+ cairo_region_destroy (client_region);
}
-#endif
-
- needs_mask = (region != NULL) || (priv->window->frame != NULL);
-
- if (region != NULL)
+ else if (priv->window->shape_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);
+ region = cairo_region_reference (priv->window->input_region);
}
else
{
@@ -2259,11 +2241,23 @@ meta_window_actor_update_x11_shape_region (MetaWindowActor *self,
region = cairo_region_create_rectangle (client_area);
}
- /* The region at this point should be constrained to the
- * bounds of the client rectangle. */
+ meta_shaped_texture_set_input_shape_region (stex, region);
+ cairo_region_destroy (region);
+}
+
+static void
+meta_window_actor_update_opaque_region (MetaWindowActor *self)
+{
+ MetaWindowActorPrivate *priv = self->priv;
+
+ 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
@@ -2275,91 +2269,13 @@ meta_window_actor_update_x11_shape_region (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);
-
- 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);
- }
-
- priv->shape_region = region;
-
- meta_window_actor_invalidate_shadow (self);
-}
-
-static void
-meta_window_actor_update_x11_input_shape_region (MetaWindowActor *self,
- cairo_rectangle_int_t *client_area)
-{
- MetaWindowActorPrivate *priv = self->priv;
- cairo_region_t *region = NULL;
-
- g_clear_pointer (&priv->input_shape_region, cairo_region_destroy);
-
-#ifdef HAVE_SHAPE
- /* Note: we currently assume that mutter never sets an input region
- * when there is a frame. */
- if (priv->window->frame == NULL && priv->window->has_input_shape)
- {
- MetaScreen *screen = priv->screen;
- MetaDisplay *display = meta_screen_get_display (screen);
- Display *xdisplay = meta_display_get_xdisplay (display);
- XRectangle *rects;
- int n_rects, ordering;
-
- /* Note we only actually query the ShapeInput shape of a window
- * when we don't have a frame because we assume currently that
- * mutter never sets an ShapeInput shape on a frame. */
- meta_error_trap_push (display);
- rects = XShapeGetRectangles (xdisplay,
- priv->window->xwindow,
- ShapeInput,
- &n_rects,
- &ordering);
- meta_error_trap_pop (display);
- if (rects)
- {
- region = region_create_from_x_rectangles (rects, n_rects,
- client_area->x,
- client_area->y);
- XFree (rects);
- }
- }
-#endif /* HAVE_SHAPE */
-
- if (region != NULL)
- {
- /* The X shape extension requires us to intersect the input
- * region with the effective bounding shape to determine the
- * effective input region.
- */
- if (priv->shape_region)
- cairo_region_intersect (region, priv->shape_region);
- else
- 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);
- }
-
- priv->input_shape_region = region;
-
- meta_shaped_texture_set_input_shape_region (META_SHAPED_TEXTURE (priv->actor),
- priv->input_shape_region);
+ priv->opaque_region = cairo_region_reference (priv->shape_region);
}
static void
@@ -2385,24 +2301,9 @@ check_needs_reshape (MetaWindowActor *self)
else
client_area.height = priv->window->rect.height;
- if (priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11)
- {
- meta_window_actor_update_x11_shape_region (self, &client_area);
- meta_window_actor_update_x11_input_shape_region (self, &client_area);
- }
- else
- {
- /* TODO: properly support setting an input region as specified
- * via the wayland protocol */
-
- g_clear_pointer (&priv->shape_region, cairo_region_destroy);
- g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
- g_clear_pointer (&priv->input_shape_region, cairo_region_destroy);
-
- priv->shape_region = cairo_region_create_rectangle (&client_area);
- priv->opaque_region = cairo_region_reference (priv->shape_region);
- priv->input_shape_region = cairo_region_reference (priv->shape_region);
- }
+ meta_window_actor_update_shape_region (self, &client_area);
+ meta_window_actor_update_input_region (self, &client_area);
+ meta_window_actor_update_opaque_region (self);
priv->needs_reshape = FALSE;
}
@@ -2463,6 +2364,8 @@ meta_window_actor_set_wayland_surface (MetaWindowActor *self,
surface);
if (surface && surface->buffer_ref.buffer)
maybe_emit_size_changed (self, surface->buffer_ref.buffer);
+
+ meta_window_actor_invalidate_shadow (self);
}
void
diff --git a/src/compositor/meta-window-group.c b/src/compositor/meta-window-group.c
index fe65f39..65771f7 100644
--- a/src/compositor/meta-window-group.c
+++ b/src/compositor/meta-window-group.c
@@ -186,7 +186,6 @@ meta_window_group_paint (ClutterActor *actor)
if (META_IS_WINDOW_ACTOR (child))
{
- MetaWindow *meta_window;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
int x, y;
@@ -201,14 +200,7 @@ meta_window_group_paint (ClutterActor *actor)
meta_window_actor_set_visible_region (window_actor, visible_region);
- /* TODO: Track the opaque regions of wayland clients.
- * Although wayland clients can report opaque window
- * regions, for now we assume that all wayland clients are
- * transparent... */
- meta_window = meta_window_actor_get_meta_window (window_actor);
-
- if (meta_window->client_type != META_WINDOW_CLIENT_TYPE_WAYLAND &&
- clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
+ if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
diff --git a/src/core/display.c b/src/core/display.c
index d62e429..7d67c2e 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -2336,59 +2336,9 @@ meta_display_handle_event (MetaDisplay *display,
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_x11_shape_changed (display->compositor,
- window);
- }
+ meta_window_update_shape_region_x11 (window);
else if (sev->kind == ShapeInput)
- {
- if (sev->shaped && !window->has_input_shape)
- {
- window->has_input_shape = TRUE;
- meta_topic (META_DEBUG_SHAPES,
- "Window %s now has an input shape\n",
- window->desc);
- }
- else if (!sev->shaped && window->has_input_shape)
- {
- window->has_input_shape = FALSE;
- meta_topic (META_DEBUG_SHAPES,
- "Window %s no longer has an input shape\n",
- window->desc);
- }
- else
- {
- meta_topic (META_DEBUG_SHAPES,
- "Window %s input shape changed\n",
- window->desc);
- }
-
- if (display->compositor)
- meta_compositor_window_x11_shape_changed (display->compositor,
- window);
- }
+ meta_window_update_input_region_x11 (window);
}
else
{
diff --git a/src/core/window-private.h b/src/core/window-private.h
index c068c35..c54036b 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -339,11 +339,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 bounding shape mask */
- guint has_shape : 1;
- /* has an input shape mask */
- guint has_input_shape : 1;
-
/* icon props have changed */
guint need_reread_icon : 1;
@@ -365,9 +360,15 @@ 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;
+ /* the input shape region for picking */
+ cairo_region_t *input_region;
+
/* if TRUE, the we have the new form of sync request counter which
* also handles application frames */
guint extended_sync_request_counter : 1;
@@ -685,7 +686,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);
@@ -699,4 +699,16 @@ 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_input_region (MetaWindow *window,
+ cairo_region_t *region);
+void meta_window_update_input_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 faf4bb2..5e87e58 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -822,8 +822,6 @@ meta_window_new_shared (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
gulong existing_wm_state,
- gboolean has_shape,
- gboolean has_input_shape,
MetaCompEffect effect,
XWindowAttributes *attrs)
{
@@ -876,9 +874,6 @@ meta_window_new_shared (MetaDisplay *display,
/* avoid tons of stack updates */
meta_stack_freeze (window->screen->stack);
- window->has_shape = has_shape;
- window->has_input_shape = has_input_shape;
-
window->rect.x = attrs->x;
window->rect.y = attrs->y;
window->rect.width = attrs->width;
@@ -1059,6 +1054,8 @@ meta_window_new_shared (MetaDisplay *display,
}
meta_display_register_x_window (display, &window->xwindow, window);
+ meta_window_update_shape_region_x11 (window);
+ meta_window_update_input_region_x11 (window);
}
/* assign the window to its group, or create a new group if needed
@@ -1425,8 +1422,6 @@ meta_window_new_for_wayland (MetaDisplay *display,
None,
TRUE,
WithdrawnState,
- FALSE, /* has shape */
- FALSE, /* has input shape */
META_COMP_EFFECT_NONE,
&attrs);
@@ -1455,8 +1450,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
gulong existing_wm_state;
MetaWindow *window;
gulong event_mask;
- gboolean has_shape = FALSE;
- gboolean has_input_shape = FALSE;
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
@@ -1576,53 +1569,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
XISelectEvents (display->xdisplay, xwindow, &mask, 1);
}
-#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;
- XRectangle *input_rectangles;
- int n_rects, ordering;
-
- 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;
-
- /* XXX: The x shape extension doesn't provide a way to only test if an
- * input shape has been specified, so we have to query and throw away the
- * rectangles. */
- meta_error_trap_push (display);
- input_rectangles = XShapeGetRectangles (display->xdisplay, xwindow,
- ShapeInput, &n_rects, &ordering);
- meta_error_trap_pop (display);
- if (input_rectangles)
- {
- if (n_rects > 1 ||
- (n_rects == 1 &&
- (input_rectangles[0].x != x_bounding ||
- input_rectangles[1].y != y_bounding ||
- input_rectangles[2].width != w_bounding ||
- input_rectangles[3].height != h_bounding)))
- {
- has_input_shape = TRUE;
- }
- XFree (input_rectangles);
- }
-
- 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);
- }
-#endif
-
/* Get rid of any borders */
if (attrs->border_width != 0)
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);
@@ -1656,8 +1602,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
xwindow,
must_be_viewable,
existing_wm_state,
- has_shape,
- has_input_shape,
effect,
attrs);
@@ -7810,14 +7754,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,
@@ -7860,11 +7815,191 @@ 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_input_region (MetaWindow *window,
+ cairo_region_t *region)
+{
+ g_clear_pointer (&window->input_region, cairo_region_destroy);
+
+ if (region != NULL)
+ window->input_region = cairo_region_reference (region);
+
if (window->display->compositor)
- meta_compositor_window_x11_shape_changed (window->display->compositor, window);
+ meta_compositor_window_shape_changed (window->display->compositor, window);
+}
+
+void
+meta_window_update_input_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);
+
+ rects = XShapeGetRectangles (window->display->xdisplay,
+ window->xwindow,
+ ShapeInput,
+ &n_rects,
+ &ordering);
+ meta_error_trap_pop (window->display);
+
+ /* XXX: The x shape extension doesn't provide a way to only test if an
+ * input shape has been specified, so we have to query and throw away the
+ * rectangles. */
+ if (rects)
+ {
+ if (n_rects > 1 ||
+ (n_rects == 1 &&
+ (rects[0].x != x_bounding ||
+ rects[1].y != y_bounding ||
+ rects[2].width != w_bounding ||
+ rects[3].height != h_bounding)))
+ region = region_create_from_x_rectangles (rects, n_rects);
+
+ XFree (rects);
+ }
+ }
+#endif /* HAVE_SHAPE */
+
+ 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_input_region (window, region);
+ cairo_region_destroy (region);
+}
+
+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 /* HAVE_SHAPE */
+
+ 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
diff --git a/src/meta/compositor.h b/src/meta/compositor.h
index de81c20..13143c9 100644
--- a/src/meta/compositor.h
+++ b/src/meta/compositor.h
@@ -64,8 +64,8 @@ void meta_compositor_manage_screen (MetaCompositor *compositor,
void meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen);
-void meta_compositor_window_x11_shape_changed (MetaCompositor *compositor,
- MetaWindow *window);
+void meta_compositor_window_shape_changed (MetaCompositor *compositor,
+ MetaWindow *window);
gboolean meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 5908ed6..267a536 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -324,18 +324,34 @@ meta_wayland_surface_frame (struct wl_client *client,
static void
meta_wayland_surface_set_opaque_region (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *region)
+ struct wl_resource *surface_resource,
+ struct wl_resource *region_resource)
{
- g_warning ("TODO: support set_opaque_region request");
+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+ MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ if (surface->window)
+ meta_window_set_opaque_region (surface->window, cairo_region_copy (region->region));
}
static void
meta_wayland_surface_set_input_region (struct wl_client *client,
- struct wl_resource *resource,
- struct wl_resource *region)
+ struct wl_resource *surface_resource,
+ struct wl_resource *region_resource)
{
- g_warning ("TODO: support set_input_region request");
+ MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+ MetaWaylandRegion *region = wl_resource_get_user_data (region_resource);
+
+ /* X11 unmanaged window */
+ if (!surface)
+ return;
+
+ if (surface->window)
+ meta_window_set_input_region (surface->window, cairo_region_copy (region->region));
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]