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.
This commit is contained in:
Richard Grenville 2012-09-12 21:01:06 +08:00
parent 6f079af2f0
commit 3abeb58690
2 changed files with 42 additions and 23 deletions

View File

@ -481,18 +481,19 @@ make_shadow(Display *dpy, double opacity,
* center (fill the complete data array) * 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) { if (cgsize > 0) {
d = shadow_top[opacity_int * (cgsize + 1) + cgsize]; d = shadow_top[opacity_int * (cgsize + 1) + cgsize];
} else { } else {
d = sum_gaussian(gaussian_map, d = sum_gaussian(gaussian_map,
opacity, center, center, width, height); opacity, center, center, width, height);
} }
memset(data, d, sheight * swidth); 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) {
if (clear_shadow && width > gsize && height > gsize) { // Clear the region in the shadow that the window would cover based
int r = gsize / 2; // on shadow_offset_{x,y} user provides
int sr = r - 2; int xstart = normalize_i_range(- (int) shadow_offset_x, 0, swidth);
int er = r + 4; int xrange = normalize_i_range(width - (int) shadow_offset_x,
for (y = sr; y < (sheight - er); y++) { 0, swidth) - xstart;
for (x = sr; x < (swidth - er); x++) { int ystart = normalize_i_range(- (int) shadow_offset_y, 0, sheight);
data[y * swidth + x] = 0; 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; return ximage;
@ -802,7 +806,6 @@ win_extents(Display *dpy, win *w) {
if (!w->shadow) { if (!w->shadow) {
double opacity = shadow_opacity; double opacity = shadow_opacity;
if (!clear_shadow) {
if (w->mode != WINDOW_SOLID) { if (w->mode != WINDOW_SOLID) {
opacity = opacity * ((double)w->opacity) / ((double)OPAQUE); opacity = opacity * ((double)w->opacity) / ((double)OPAQUE);
} }
@ -810,7 +813,6 @@ win_extents(Display *dpy, win *w) {
if (HAS_FRAME_OPACITY(w)) { if (HAS_FRAME_OPACITY(w)) {
opacity = opacity * frame_opacity; opacity = opacity * frame_opacity;
} }
}
w->shadow = shadow_picture( w->shadow = shadow_picture(
dpy, opacity, w->alpha_pict, dpy, opacity, w->alpha_pict,
@ -2784,7 +2786,7 @@ main(int argc, char **argv) {
shadow_radius = atoi(optarg); shadow_radius = atoi(optarg);
break; break;
case 'o': case 'o':
shadow_opacity = atof(optarg); shadow_opacity = normalize_d(atof(optarg));
break; break;
case 'l': case 'l':
shadow_offset_x = atoi(optarg); shadow_offset_x = atoi(optarg);

View File

@ -152,6 +152,23 @@ extern int root_height, root_width;
// inline functions must be made static to compile correctly under clang: // inline functions must be made static to compile correctly under clang:
// http://clang.llvm.org/compatibility.html#inline // 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. * Normalize a double value to 0.\ 0 - 1.\ 0.
* *