diff --git a/src/render.c b/src/render.c index 8e316ba..e7d599e 100644 --- a/src/render.c +++ b/src/render.c @@ -211,7 +211,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) { // Invert window color, if required if (bkend_use_xrender(ps) && w->invert_color) { xcb_render_picture_t newpict = - x_create_picture(ps, wid, hei, w->pictfmt, 0, NULL); + x_create_picture_with_pictfmt(ps, wid, hei, w->pictfmt, 0, NULL); if (newpict) { // Apply clipping region to save some CPU if (reg_paint) { @@ -684,7 +684,8 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wi // Directly copying from tgt_buffer to it does not work, so we create a // Picture in the middle. - xcb_render_picture_t tmp_picture = x_create_picture(ps, wid, hei, NULL, 0, NULL); + xcb_render_picture_t tmp_picture = + x_create_picture_with_pictfmt(ps, wid, hei, NULL, 0, NULL); if (!tmp_picture) { log_error("Failed to build intermediate Picture."); @@ -991,7 +992,7 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win // Then we create a new picture, and copy content to it xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(ps, ps->vis); - xcb_render_picture_t new_pict = x_create_picture( + xcb_render_picture_t new_pict = x_create_picture_with_pictfmt( ps, ps->root_width, ps->root_height, pictfmt, 0, NULL); xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, None, new_pict, 0, 0, 0, diff --git a/src/x.c b/src/x.c index b56dd2a..781526f 100644 --- a/src/x.c +++ b/src/x.c @@ -188,7 +188,7 @@ x_create_picture_with_standard_and_pixmap( * Create an picture. */ xcb_render_picture_t -x_create_picture(session_t *ps, int wid, int hei, +x_create_picture_with_pictfmt(session_t *ps, int wid, int hei, xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, const xcb_render_create_picture_value_list_t *attr) { @@ -214,6 +214,15 @@ x_create_picture(session_t *ps, int wid, int hei, return picture; } +xcb_render_picture_t +x_create_picture_with_visual(session_t *ps, int w, int h, + xcb_visualid_t visual, unsigned long valuemask, + const xcb_render_create_picture_value_list_t *attr) +{ + xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(ps, visual); + return x_create_picture_with_pictfmt(ps, w, h, pictfmt, valuemask, attr); +} + bool x_fetch_region(session_t *ps, xcb_xfixes_region_t r, pixman_region32_t *res) { xcb_generic_error_t *e = NULL; xcb_xfixes_fetch_region_reply_t *xr = xcb_xfixes_fetch_region_reply(ps->c, @@ -263,6 +272,19 @@ void x_set_picture_clip_region(session_t *ps, xcb_render_picture_t pict, return; } +void x_clear_picture_clip_region(session_t *ps, xcb_render_picture_t pict) { + xcb_render_change_picture_value_list_t v = { + .clipmask = None + }; + xcb_generic_error_t *e = + xcb_request_check(ps->c, xcb_render_change_picture(ps->c, pict, + XCB_RENDER_CP_CLIP_MASK, &v)); + if (e) + log_error("failed to clear clip region"); + free(e); + return; +} + /** * X11 error handler function. * @@ -390,3 +412,38 @@ x_validate_pixmap(session_t *ps, xcb_pixmap_t pxmap) { return XGetGeometry(ps->dpy, pxmap, &rroot, &rx, &ry, &rwid, &rhei, &rborder, &rdepth) && rwid && rhei; } +/// Names of root window properties that could point to a pixmap of +/// background. +static const char *background_props_str[] = { + "_XROOTPMAP_ID", + "_XSETROOT_ID", + 0, +}; + +xcb_pixmap_t x_get_root_back_pixmap(session_t *ps) { + xcb_pixmap_t pixmap = XCB_NONE; + + // Get the values of background attributes + for (int p = 0; background_props_str[p]; p++) { + xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); + winprop_t prop = + wid_get_prop(ps, ps->root, prop_atom, 1, XCB_ATOM_PIXMAP, 32); + if (prop.nitems) { + pixmap = *prop.p32; + free_winprop(&prop); + break; + } + free_winprop(&prop); + } + + return pixmap; +} + +bool x_atom_is_background_prop(session_t *ps, xcb_atom_t atom) { + for (int p = 0; background_props_str[p]; p++) { + xcb_atom_t prop_atom = get_atom(ps, background_props_str[p]); + if (prop_atom == atom) + return true; + } + return false; +} diff --git a/src/x.h b/src/x.h index 40d02ab..b16a821 100644 --- a/src/x.h +++ b/src/x.h @@ -116,16 +116,23 @@ attr_nonnull(1); * Create an picture. */ xcb_render_picture_t -x_create_picture(session_t *ps, int wid, int hei, +x_create_picture_with_pictfmt(session_t *ps, int wid, int hei, xcb_render_pictforminfo_t *pictfmt, unsigned long valuemask, const xcb_render_create_picture_value_list_t *attr); +xcb_render_picture_t +x_create_picture_with_visual(session_t *ps, int w, int h, + xcb_visualid_t visual, 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, xcb_xfixes_region_t 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 *); +void x_clear_picture_clip_region(session_t *ps, xcb_render_picture_t pict); + /** * X11 error handler function. * @@ -154,3 +161,9 @@ free_winprop(winprop_t *pprop) { pprop->r = NULL; pprop->nitems = 0; } +/// Get the back pixmap of the root window +xcb_pixmap_t x_get_root_back_pixmap(session_t *ps); + +/// Return true if the atom refers to a property name that is used for the +/// root window background pixmap +bool x_atom_is_background_prop(session_t *ps, xcb_atom_t atom);