diff --git a/Makefile b/Makefile index 219511b..6df5059 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ MANDIR ?= $(PREFIX)/share/man/man1 APPDIR ?= $(PREFIX)/share/applications ICODIR ?= $(PREFIX)/share/icons/hicolor/ -PACKAGES = x11 x11-xcb xcb-renderutil xcb-render xcb-damage xcb-randr xcb-composite xcb-shape xcb-image xcb-xfixes xfixes xext +PACKAGES = x11 x11-xcb xcb-renderutil xcb-render xcb-damage xcb-randr xcb-composite xcb-shape xcb-image xcb-xfixes xfixes xext pixman-1 LIBS = -lm -lrt INCS = diff --git a/src/region.h b/src/region.h new file mode 100644 index 0000000..713b4e7 --- /dev/null +++ b/src/region.h @@ -0,0 +1,25 @@ +#pragma once +#include +#include +#include "utils.h" +typedef struct pixman_region32 pixman_region32_t; +typedef struct pixman_box32 pixman_box32_t; +typedef pixman_region32_t region_t; +typedef pixman_box32_t rect_t; + +RC_TYPE(region_t, rc_region, pixman_region32_init, pixman_region32_fini, static inline) + +/// copy a region_t +static inline void +copy_region_(region_t *dst, const region_t *p) { + pixman_region32_copy(dst, (region_t *)p); +} + +static inline void +dump_region_(const region_t *x) { + int nrects; + const rect_t *rects = pixman_region32_rectangles((region_t *)x, &nrects); + fprintf(stderr, "nrects: %d\n", nrects); + for (int i = 0; i < nrects; i++) + fprintf(stderr, "(%d, %d) - (%d, %d)\n", rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); +} diff --git a/src/x.c b/src/x.c index a678892..d6abe8e 100644 --- a/src/x.c +++ b/src/x.c @@ -2,6 +2,8 @@ #include #include +#include +#include #include "common.h" #include "x.h" @@ -208,3 +210,54 @@ x_create_picture(session_t *ps, int wid, int hei, return picture; } + +bool x_fetch_region(session_t *ps, XserverRegion r, pixman_region32_t *res) { + xcb_generic_error_t *e = NULL; + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(c, + xcb_xfixes_fetch_region(c, r), &e); + if (!xr) { + printf_errf("(): failed to fetch rectangles"); + return false; + } + + int nrect = xcb_xfixes_fetch_region_rectangles_length(xr); + pixman_box32_t *b = calloc(nrect, sizeof *b); + xcb_rectangle_t *xrect = xcb_xfixes_fetch_region_rectangles(xr); + for (int i = 0; i < nrect; i++) { + b[i] = (pixman_box32_t) { + .x1 = xrect[i].x, + .y1 = xrect[i].y, + .x2 = xrect[i].x + xrect[i].width, + .y2 = xrect[i].y + xrect[i].height + }; + } + bool ret = pixman_region32_init_rects(res, b, nrect); + free(b); + free(xr); + return ret; +} + +void x_set_picture_clip_region(session_t *ps, xcb_render_picture_t pict, + int clip_x_origin, int clip_y_origin, const region_t *reg) { + int nrects; + const rect_t *rects = pixman_region32_rectangles((region_t *)reg, &nrects); + xcb_rectangle_t *xrects = calloc(nrects, sizeof *xrects); + for (int i = 0; i < nrects; i++) + xrects[i] = (xcb_rectangle_t){ + .x = rects[i].x1, + .y = rects[i].y1, + .width = rects[i].x2 - rects[i].x1, + .height = rects[i].y2 - rects[i].y1, + }; + + xcb_connection_t *c = XGetXCBConnection(ps->dpy); + xcb_generic_error_t *e = + xcb_request_check(c, xcb_render_set_picture_clip_rectangles_checked(c, pict, + clip_x_origin, clip_y_origin, nrects, xrects)); + if (e) + printf_errf("(): failed to set clip region"); + free(e); + free(xrects); + return; +} diff --git a/src/x.h b/src/x.h index cc2734a..e539a93 100644 --- a/src/x.h +++ b/src/x.h @@ -4,8 +4,12 @@ #include #include #include + +#include "region.h" + typedef struct session session_t; typedef struct winprop winprop_t; + /** * Get a specific attribute of a window. * @@ -66,3 +70,9 @@ xcb_render_picture_t x_create_picture(session_t *ps, int wid, int hei, xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, const xcb_render_create_picture_value_list_t *attr); + +/// Fetch a X region and store it in a pixman region +bool x_fetch_region(session_t *ps, XserverRegion r, region_t *res); + +void x_set_picture_clip_region(session_t *ps, xcb_render_picture_t, + int clip_x_origin, int clip_y_origin, const region_t *);