[metacity] window: get bounding shape region
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [metacity] window: get bounding shape region
- Date: Sun, 12 Mar 2017 11:19:09 +0000 (UTC)
commit 619bb121fb511847c01769941dd6c94b606e3695
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sun Mar 12 12:06:04 2017 +0200
window: get bounding shape region
src/core/display.c | 2 +
src/core/window-private.h | 5 ++
src/core/window.c | 135 +++++++++++++++++++++++++++++++++++++--------
3 files changed, 119 insertions(+), 23 deletions(-)
---
diff --git a/src/core/display.c b/src/core/display.c
index 421afb4..848e3e2 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1850,6 +1850,8 @@ event_callback (XEvent *event,
window->desc);
}
+ meta_window_update_shape_region (window);
+
if (window->frame)
{
window->frame->need_reapply_frame_shape = TRUE;
diff --git a/src/core/window-private.h b/src/core/window-private.h
index 4eba584..b7949d9 100644
--- a/src/core/window-private.h
+++ b/src/core/window-private.h
@@ -343,6 +343,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;
@@ -728,4 +731,6 @@ MetaFrameType meta_window_get_frame_type (MetaWindow *window);
gboolean meta_window_updates_are_frozen (MetaWindow *window);
+void meta_window_update_shape_region (MetaWindow *window);
+
#endif
diff --git a/src/core/window.c b/src/core/window.c
index 9b4f5ac..de34e64 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -273,7 +273,6 @@ meta_window_new (MetaDisplay *display,
gulong existing_wm_state;
gulong event_mask;
MetaMoveResizeFlags flags;
- gboolean has_shape;
meta_display_grab (display);
meta_error_trap_push (display); /* Push a trap over all of window
@@ -352,28 +351,8 @@ meta_window_new (MetaDisplay *display,
*/
XSelectInput (display->xdisplay, xwindow, attrs.your_event_mask | event_mask);
- has_shape = FALSE;
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);
/* Get rid of any borders */
if (attrs.border_width != 0)
@@ -430,7 +409,7 @@ meta_window_new (MetaDisplay *display,
/* avoid tons of stack updates */
meta_stack_freeze (window->screen->stack);
- window->has_shape = has_shape;
+ window->has_shape = FALSE;
window->rect.x = attrs.x;
window->rect.y = attrs.y;
@@ -523,6 +502,7 @@ meta_window_new (MetaDisplay *display,
window->disable_sync = FALSE;
window->attached = FALSE;
window->frame_bounds = NULL;
+ window->shape_region = NULL;
window->opaque_region = NULL;
window->opacity = 0xffffffff;
@@ -599,6 +579,8 @@ meta_window_new (MetaDisplay *display,
meta_display_register_x_window (display, &window->xwindow, window);
+ meta_window_update_shape_region (window);
+
/* assign the window to its group, or create a new group if needed
*/
window->group = NULL;
@@ -1271,6 +1253,9 @@ meta_window_free (MetaWindow *window,
if (window->frame_bounds)
cairo_region_destroy (window->frame_bounds);
+ if (window->shape_region)
+ cairo_region_destroy (window->shape_region);
+
if (window->opaque_region)
cairo_region_destroy (window->opaque_region);
@@ -9106,3 +9091,107 @@ meta_window_is_attached_dialog (MetaWindow *window)
{
return window->attached;
}
+
+void
+meta_window_update_shape_region (MetaWindow *window)
+{
+ cairo_region_t *shape_region;
+ int bshaped;
+ int xbs;
+ int ybs;
+ unsigned int wbs;
+ unsigned int hbs;
+ int cshaped;
+ int xcs;
+ int ycs;
+ unsigned int wcs;
+ unsigned int hcs;
+
+ if (!window->display->have_shape)
+ return;
+
+ meta_error_trap_push (window->display);
+
+ XShapeQueryExtents (window->display->xdisplay, window->xwindow,
+ &bshaped, &xbs, &ybs, &wbs, &hbs,
+ &cshaped, &xcs, &ycs, &wcs, &hcs);
+
+ if (bshaped)
+ {
+ XRectangle *rects;
+ int n_rects;
+ int ordering;
+
+ window->has_shape = TRUE;
+
+ rects = XShapeGetRectangles (window->display->xdisplay, window->xwindow,
+ ShapeBounding, &n_rects, &ordering);
+
+ if (rects)
+ {
+ cairo_rectangle_int_t cairo_rects[n_rects];
+ int i;
+
+ 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;
+ }
+
+ shape_region = cairo_region_create_rectangles (cairo_rects, n_rects);
+ XFree (rects);
+ }
+ else
+ {
+ shape_region = NULL;
+ }
+ }
+ else
+ {
+ window->has_shape = FALSE;
+ shape_region = NULL;
+ }
+
+ meta_error_trap_pop (window->display);
+
+ if (shape_region != NULL)
+ {
+ cairo_rectangle_int_t client_area;
+ cairo_region_overlap_t overlap;
+
+ 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 (shape_region, &client_area);
+
+ /* Some applications might explicitly set their bounding region
+ * to the client area. Detect these cases, and throw out the
+ * bounding region in this case.
+ */
+ overlap = cairo_region_contains_rectangle (shape_region, &client_area);
+ if (overlap == CAIRO_REGION_OVERLAP_IN)
+ g_clear_pointer (&shape_region, cairo_region_destroy);
+ }
+
+ if (cairo_region_equal (window->shape_region, shape_region))
+ {
+ cairo_region_destroy (shape_region);
+ return;
+ }
+
+ g_clear_pointer (&window->shape_region, cairo_region_destroy);
+ window->shape_region = shape_region;
+
+ meta_compositor_window_shape_changed (window->display->compositor, window);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]