From 3abeb58690cbfce962640331fdd41d9b312147be Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Wed, 12 Sep 2012 21:01:06 +0800 Subject: [PATCH] Bug fix: Issue #40: -z does not work as expected More information in the issue report. - Let window opacity affect the opacity of its shadow and frames even if -z is enabled. - Check for the range of -o to eliminate potential segfault. --- src/compton.c | 48 +++++++++++++++++++++++++----------------------- src/compton.h | 17 +++++++++++++++++ 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/compton.c b/src/compton.c index 3101771..d54b52a 100644 --- a/src/compton.c +++ b/src/compton.c @@ -481,18 +481,19 @@ make_shadow(Display *dpy, double opacity, * center (fill the complete data array) */ - if (!clear_shadow) { + // If clear_shadow is enabled and the border & corner shadow (which + // later will be filled) could entirely cover the area of the shadow + // that will be displayed, do not bother filling other pixels. If it + // can't, we must fill the other pixels here. + if (!(clear_shadow && shadow_offset_x <= 0 && shadow_offset_x >= -cgsize + && shadow_offset_y <= 0 && shadow_offset_y >= -cgsize)) { if (cgsize > 0) { d = shadow_top[opacity_int * (cgsize + 1) + cgsize]; } else { d = sum_gaussian(gaussian_map, opacity, center, center, width, height); } - memset(data, d, sheight * swidth); - } else { - // zero the pixmap - memset(data, 0, sheight * swidth); } /* @@ -556,16 +557,19 @@ make_shadow(Display *dpy, double opacity, } } - // zero extra pixels - if (clear_shadow && width > gsize && height > gsize) { - int r = gsize / 2; - int sr = r - 2; - int er = r + 4; - for (y = sr; y < (sheight - er); y++) { - for (x = sr; x < (swidth - er); x++) { - data[y * swidth + x] = 0; - } - } + if (clear_shadow) { + // Clear the region in the shadow that the window would cover based + // on shadow_offset_{x,y} user provides + int xstart = normalize_i_range(- (int) shadow_offset_x, 0, swidth); + int xrange = normalize_i_range(width - (int) shadow_offset_x, + 0, swidth) - xstart; + int ystart = normalize_i_range(- (int) shadow_offset_y, 0, sheight); + int yend = normalize_i_range(height - (int) shadow_offset_y, + 0, sheight); + int y; + + for (y = ystart; y < yend; y++) + memset(&data[y * swidth + xstart], 0, xrange); } return ximage; @@ -802,14 +806,12 @@ win_extents(Display *dpy, win *w) { if (!w->shadow) { double opacity = shadow_opacity; - if (!clear_shadow) { - if (w->mode != WINDOW_SOLID) { - opacity = opacity * ((double)w->opacity) / ((double)OPAQUE); - } + if (w->mode != WINDOW_SOLID) { + opacity = opacity * ((double)w->opacity) / ((double)OPAQUE); + } - if (HAS_FRAME_OPACITY(w)) { - opacity = opacity * frame_opacity; - } + if (HAS_FRAME_OPACITY(w)) { + opacity = opacity * frame_opacity; } w->shadow = shadow_picture( @@ -2784,7 +2786,7 @@ main(int argc, char **argv) { shadow_radius = atoi(optarg); break; case 'o': - shadow_opacity = atof(optarg); + shadow_opacity = normalize_d(atof(optarg)); break; case 'l': shadow_offset_x = atoi(optarg); diff --git a/src/compton.h b/src/compton.h index ea90696..9a8dd85 100644 --- a/src/compton.h +++ b/src/compton.h @@ -152,6 +152,23 @@ extern int root_height, root_width; // inline functions must be made static to compile correctly under clang: // http://clang.llvm.org/compatibility.html#inline +/** + * Normalize an int value to a specific range. + * + * @param i int value to normalize + * @param min minimal value + * @param max maximum value + * @return normalized value + */ +static inline double normalize_i_range(int i, int min, int max) { + if (i > max) + return max; + if (i < min) + return min; + + return i; +} + /** * Normalize a double value to 0.\ 0 - 1.\ 0. *