diff --git a/common.h b/common.h index 04eae104b..2a98253d5 100644 --- a/common.h +++ b/common.h @@ -403,6 +403,8 @@ typedef struct { /// Whether to paint on X Composite overlay window instead of root /// window. bool paint_on_overlay; + /// Resize damage for a specific number of pixels. + int resize_damage; /// Whether to unredirect all windows if a full-screen opaque window /// is detected. bool unredir_if_possible; diff --git a/compton.c b/compton.c index 7935e4c16..cfd773c69 100644 --- a/compton.c +++ b/compton.c @@ -4235,6 +4235,11 @@ usage(void) { " --blur-kern '7,7,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003,0.000102,0.003494,0.029143,0.059106,0.029143,0.003494,0.000102,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.001723,0.059106,0.493069,0.493069,0.059106,0.001723,0.000849,0.029143,0.243117,0.493069,0.243117,0.029143,0.000849,0.000102,0.003494,0.029143,0.059106,0.029143,0.003494,0.000102,0.000003,0.000102,0.000849,0.001723,0.000849,0.000102,0.000003'\n" "--blur-background-exclude condition\n" " Exclude conditions for background blur.\n" + "--resize-damage integer\n" + " Resize damaged region by a specific number of pixels. A positive\n" + " value enlarges it while a negative one shrinks it. Useful for\n" + " fixing the line corruption issues of blur. May or may not\n" + " work with --glx-no-stencil. Shrinking doesn't function correctly.\n" "--invert-color-include condition\n" " Specify a list of conditions of windows that should be painted with\n" " inverted color. Resource-hogging, and is not well tested.\n" @@ -4861,6 +4866,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { { "glx-swap-method", required_argument, NULL, 299 }, { "fade-exclude", required_argument, NULL, 300 }, { "blur-kern", required_argument, NULL, 301 }, + { "resize-damage", required_argument, NULL, 302 }, // Must terminate with a NULL entry { NULL, 0, NULL, 0 }, }; @@ -5089,6 +5095,9 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { free(ps->o.blur_kern); if (!(ps->o.blur_kern = parse_matrix(ps, optarg))) exit(1); + case 302: + // --resize-damage + ps->o.resize_damage = atoi(optarg); break; default: usage(); @@ -5952,6 +5961,7 @@ session_init(session_t *ps_old, int argc, char **argv) { .synchronize = false, .detect_rounded_corners = false, .paint_on_overlay = false, + .resize_damage = 0, .unredir_if_possible = false, .dbus = false, .benchmark = 0, @@ -6577,6 +6587,7 @@ session_run(session_t *ps) { if (!ps->redirected) free_region(ps, &ps->all_damage); + resize_region(ps, ps->all_damage, ps->o.resize_damage); if (ps->all_damage && !is_region_empty(ps, ps->all_damage, NULL)) { static int paint = 0; paint_all(ps, ps->all_damage, t); diff --git a/compton.h b/compton.h index 09b1a4bfb..6b23e1d53 100644 --- a/compton.h +++ b/compton.h @@ -850,19 +850,69 @@ get_screen_region(session_t *ps) { return XFixesCreateRegion(ps->dpy, &r, 1); } +/** + * Resize a region. + */ +static inline void +resize_region(session_t *ps, XserverRegion region, short mod) { + if (!mod || !region) return; + + int nrects = 0, nnewrects = 0; + XRectangle *newrects = NULL; + XRectangle *rects = XFixesFetchRegion(ps->dpy, region, &nrects); + if (!rects || !nrects) + goto resize_region_end; + + // Allocate memory for new rectangle list, because I don't know if it's + // safe to write in the memory Xlib allocates + newrects = calloc(nrects, sizeof(XRectangle)); + if (!newrects) { + printf_errf("(): Failed to allocate memory."); + exit(1); + } + + // Loop through all rectangles + for (int i = 0; i < nrects; ++i) { + int x1 = max_i(rects[i].x - mod, 0); + int y1 = max_i(rects[i].y - mod, 0); + int x2 = min_i(rects[i].x + rects[i].width + mod, ps->root_width); + int y2 = min_i(rects[i].y + rects[i].height + mod, ps->root_height); + int wid = x2 - x1; + int hei = y2 - y1; + if (wid <= 0 || hei <= 0) + continue; + newrects[nnewrects].x = x1; + newrects[nnewrects].y = y1; + newrects[nnewrects].width = wid; + newrects[nnewrects].height = hei; + ++nnewrects; + } + + // Set region + XFixesSetRegion(ps->dpy, region, newrects, nnewrects); + +resize_region_end: + cxfree(rects); + free(newrects); +} + /** * Dump a region. */ static inline void dump_region(const session_t *ps, XserverRegion region) { - int nrects = 0, i; - XRectangle *rects = XFixesFetchRegion(ps->dpy, region, &nrects); - if (!rects) - return; + int nrects = 0; + XRectangle *rects = NULL; + if (!rects && region) + rects = XFixesFetchRegion(ps->dpy, region, &nrects); - for (i = 0; i < nrects; ++i) + printf_dbgf("(%#010lx): %d rects\n", region, nrects); + if (!rects) return; + for (int i = 0; i < nrects; ++i) printf("Rect #%d: %8d, %8d, %8d, %8d\n", i, rects[i].x, rects[i].y, rects[i].width, rects[i].height); + putchar('\n'); + fflush(stdout); cxfree(rects); } diff --git a/opengl.c b/opengl.c index 8fb4e153e..4d6d65947 100644 --- a/opengl.c +++ b/opengl.c @@ -246,6 +246,7 @@ glx_init_blur(session_t *ps) { #endif } ps->glx_frag_shader_blur = glx_create_shader(GL_FRAGMENT_SHADER, shader_str); + free(shader_str); } if (!ps->glx_frag_shader_blur) {