summaryrefslogtreecommitdiffstats
path: root/compton.c
diff options
context:
space:
mode:
Diffstat (limited to 'compton.c')
-rw-r--r--compton.c134
1 files changed, 120 insertions, 14 deletions
diff --git a/compton.c b/compton.c
index c55d045d8..74bebfb47 100644
--- a/compton.c
+++ b/compton.c
@@ -1670,6 +1670,16 @@ rebuild_screen_reg(session_t *ps) {
ps->screen_reg = get_screen_region(ps);
}
+/**
+ * Rebuild <code>shadow_exclude_reg</code>.
+ */
+static void
+rebuild_shadow_exclude_reg(session_t *ps) {
+ free_region(ps, &ps->shadow_exclude_reg);
+ XRectangle rect = geom_to_rect(ps, &ps->o.shadow_exclude_reg_geom, NULL);
+ ps->shadow_exclude_reg = rect_to_reg(ps, &rect);
+}
+
static void
paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t) {
if (!region_real)
@@ -1781,6 +1791,10 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
XFixesIntersectRegion(ps->dpy, reg_paint, region, w->extents);
}
+ if (ps->shadow_exclude_reg)
+ XFixesSubtractRegion(ps->dpy, reg_paint, reg_paint,
+ ps->shadow_exclude_reg);
+
// Might be worthwhile to crop the region to shadow border
{
XRectangle rec_shadow_border = {
@@ -2888,10 +2902,12 @@ configure_win(session_t *ps, XConfigureEvent *ce) {
XRenderFreePicture(ps->dpy, ps->tgt_buffer);
ps->tgt_buffer = None;
}
+
ps->root_width = ce->width;
ps->root_height = ce->height;
rebuild_screen_reg(ps);
+ rebuild_shadow_exclude_reg(ps);
#ifdef CONFIG_VSYNC_OPENGL
if (BKEND_GLX == ps->o.backend)
@@ -4385,6 +4401,11 @@ usage(int ret) {
" this. Note we do not distinguish 100% and unset, and we don't make\n"
" any guarantee about possible conflicts with other programs that set\n"
" _NET_WM_WINDOW_OPACITY on frame or client windows.\n"
+ "--shadow-exclude-reg geometry\n"
+ " Specify a X geometry that describes the region in which shadow\n"
+ " should not be painted in, such as a dock window region.\n"
+ " Use --shadow-exclude-reg \'x10+0-0\', for example, if the 10 pixels\n"
+ " on the bottom of the screen should not have shadows painted on.\n"
"--backend backend\n"
" Choose backend. Possible choices are xrender and glx" WARNING ".\n"
"--glx-no-stencil\n"
@@ -4720,6 +4741,83 @@ parse_conv_kern_lst(session_t *ps, const char *src, XFixed **dest, int max) {
}
/**
+ * Parse a X geometry.
+ */
+static inline bool
+parse_geometry(session_t *ps, const char *src, geometry_t *dest) {
+ geometry_t geom = { .wid = -1, .hei = -1, .x = -1, .y = -1 };
+ long val = 0L;
+ char *endptr = NULL;
+
+#define T_STRIPSPACE() do { \
+ while (*src && isspace(*src)) ++src; \
+ if (!*src) goto parse_geometry_end; \
+} while(0)
+
+ T_STRIPSPACE();
+
+ // Parse width
+ // Must be base 10, because "0x0..." may appear
+ if (!('+' == *src || '-' == *src)) {
+ val = strtol(src, &endptr, 10);
+ if (endptr && src != endptr) {
+ geom.wid = val;
+ assert(geom.wid >= 0);
+ src = endptr;
+ }
+ T_STRIPSPACE();
+ }
+
+ // Parse height
+ if ('x' == *src) {
+ ++src;
+ val = strtol(src, &endptr, 10);
+ if (endptr && src != endptr) {
+ geom.hei = val;
+ if (geom.hei < 0) {
+ printf_errf("(\"%s\"): Invalid height.", src);
+ return false;
+ }
+ src = endptr;
+ }
+ T_STRIPSPACE();
+ }
+
+ // Parse x
+ if ('+' == *src || '-' == *src) {
+ val = strtol(src, &endptr, 10);
+ if (endptr && src != endptr) {
+ geom.x = val;
+ if ('-' == *src && geom.x <= 0)
+ geom.x -= 2;
+ src = endptr;
+ }
+ T_STRIPSPACE();
+ }
+
+ // Parse y
+ if ('+' == *src || '-' == *src) {
+ val = strtol(src, &endptr, 10);
+ if (endptr && src != endptr) {
+ geom.y = val;
+ if ('-' == *src && geom.y <= 0)
+ geom.y -= 2;
+ src = endptr;
+ }
+ T_STRIPSPACE();
+ }
+
+ if (*src) {
+ printf_errf("(\"%s\"): Trailing characters.", src);
+ return false;
+ }
+
+parse_geometry_end:
+ *dest = geom;
+ return true;
+}
+
+/**
* Parse a list of opacity rules.
*/
static inline bool
@@ -5118,6 +5216,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
{ "resize-damage", required_argument, NULL, 302 },
{ "glx-use-gpushader4", no_argument, NULL, 303 },
{ "opacity-rule", required_argument, NULL, 304 },
+ { "shadow-exclude-reg", required_argument, NULL, 305 },
// Must terminate with a NULL entry
{ NULL, 0, NULL, 0 },
};
@@ -5356,6 +5455,11 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
if (!parse_rule_opacity(ps, optarg))
exit(1);
break;
+ case 305:
+ // --shadow-exclude-reg
+ if (!parse_geometry(ps, optarg, &ps->o.shadow_exclude_reg_geom))
+ exit(1);
+ break;
default:
usage(1);
break;
@@ -5440,6 +5544,8 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
}
memcpy(ps->o.blur_kerns[0], &convolution_blur, sizeof(convolution_blur));
}
+
+ rebuild_shadow_exclude_reg(ps);
}
/**
@@ -6434,9 +6540,6 @@ session_init(session_t *ps_old, int argc, char **argv) {
}
}
- // Second pass
- get_cfg(ps, argc, argv, false);
-
XSetErrorHandler(error);
if (ps->o.synchronize) {
XSynchronize(ps->dpy, 1);
@@ -6448,6 +6551,17 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->vis = DefaultVisual(ps->dpy, ps->scr);
ps->depth = DefaultDepth(ps->dpy, ps->scr);
+ // Start listening to events on root earlier to catch all possible
+ // root geometry changes
+ XSelectInput(ps->dpy, ps->root,
+ SubstructureNotifyMask
+ | ExposureMask
+ | StructureNotifyMask
+ | PropertyChangeMask);
+
+ ps->root_width = DisplayWidth(ps->dpy, ps->scr);
+ ps->root_height = DisplayHeight(ps->dpy, ps->scr);
+
if (!XRenderQueryExtension(ps->dpy,
&ps->render_event, &ps->render_error)) {
fprintf(stderr, "No render extension\n");
@@ -6485,6 +6599,9 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->shape_exists = true;
}
+ // Second pass
+ get_cfg(ps, argc, argv, false);
+
// Query X RandR
if (ps->o.sw_opti && !ps->o.refresh_rate) {
if (XRRQueryExtension(ps->dpy, &ps->randr_event, &ps->randr_error))
@@ -6510,17 +6627,6 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->o.dbe = false;
}
- // Start listening to events on root earlier to catch all possible
- // root geometry changes
- XSelectInput(ps->dpy, ps->root,
- SubstructureNotifyMask
- | ExposureMask
- | StructureNotifyMask
- | PropertyChangeMask);
-
- ps->root_width = DisplayWidth(ps->dpy, ps->scr);
- ps->root_height = DisplayHeight(ps->dpy, ps->scr);
-
rebuild_screen_reg(ps);
// Overlay must be initialized before double buffer, and before creation