Bug fix #17: Try to fix artifacts after animating/shading shaped wins in Openbox
- Correct design mistakes in win_get_region_noframe(). I must be sleepwalking when I wrote that thing! - Intersect border_size with window region rectangle because Openbox is offering wrong window shapes larger than the window rectangle for shaped windows. Shame on you, Openbox. - Change logic in reg_ignore calculation as border_size is now intersected with window rectangle and we don't need to do this here again. - Rewrite window painting with frame opacity part in win_paint_win() to deal with absurd frame widths WM offers. Again, Openbox, this is your fault. - As I'm in a pretty bad state (continuously working on compton for 10+ hours without rest...), all these changes are not well tested, and bugs are to be expected.
This commit is contained in:
parent
46dfd1a766
commit
66d3f30978
137
src/compton.c
137
src/compton.c
|
@ -1194,12 +1194,15 @@ static XserverRegion
|
||||||
win_get_region_noframe(Display *dpy, win *w) {
|
win_get_region_noframe(Display *dpy, win *w) {
|
||||||
XRectangle r;
|
XRectangle r;
|
||||||
|
|
||||||
r.x = w->a.x + w->left_width;
|
r.x = w->a.x + w->a.border_width + w->left_width;
|
||||||
r.y = w->a.y + w->top_width;
|
r.y = w->a.y + w->a.border_width + w->top_width;
|
||||||
r.width = w->a.width;
|
r.width = max_i(w->a.width - w->left_width - w->right_width, 0);
|
||||||
r.height = w->a.height;
|
r.height = max_i(w->a.height - w->top_width - w->bottom_width, 0);
|
||||||
|
|
||||||
return XFixesCreateRegion(dpy, &r, 1);
|
if (r.width > 0 && r.height > 0)
|
||||||
|
return XFixesCreateRegion(dpy, &r, 1);
|
||||||
|
else
|
||||||
|
return XFixesCreateRegion(dpy, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1249,28 +1252,38 @@ win_extents(Display *dpy, win *w) {
|
||||||
|
|
||||||
static XserverRegion
|
static XserverRegion
|
||||||
border_size(Display *dpy, win *w) {
|
border_size(Display *dpy, win *w) {
|
||||||
XserverRegion border;
|
// Start with the window rectangular region
|
||||||
|
XserverRegion fin = win_get_region(dpy, w);
|
||||||
|
|
||||||
/*
|
// Only request for a bounding region if the window is shaped
|
||||||
* if window doesn't exist anymore, this will generate an error
|
if (w->bounding_shaped) {
|
||||||
* as well as not generate a region. Perhaps a better XFixes
|
/*
|
||||||
* architecture would be to have a request that copies instead
|
* if window doesn't exist anymore, this will generate an error
|
||||||
* of creates, that way you'd just end up with an empty region
|
* as well as not generate a region. Perhaps a better XFixes
|
||||||
* instead of an invalid XID.
|
* architecture would be to have a request that copies instead
|
||||||
*/
|
* of creates, that way you'd just end up with an empty region
|
||||||
|
* instead of an invalid XID.
|
||||||
|
*/
|
||||||
|
|
||||||
border = XFixesCreateRegionFromWindow(
|
XserverRegion border = XFixesCreateRegionFromWindow(
|
||||||
dpy, w->id, WindowRegionBounding);
|
dpy, w->id, WindowRegionBounding);
|
||||||
|
|
||||||
if (!border)
|
if (!border)
|
||||||
return None;
|
return fin;
|
||||||
|
|
||||||
/* translate this */
|
// Translate the region to the correct place
|
||||||
XFixesTranslateRegion(dpy, border,
|
XFixesTranslateRegion(dpy, border,
|
||||||
w->a.x + w->a.border_width,
|
w->a.x + w->a.border_width,
|
||||||
w->a.y + w->a.border_width);
|
w->a.y + w->a.border_width);
|
||||||
|
|
||||||
return border;
|
// Intersect the bounding region we got with the window rectangle, to
|
||||||
|
// make sure the bounding region is not bigger than the window
|
||||||
|
// rectangle
|
||||||
|
XFixesIntersectRegion(dpy, fin, fin, border);
|
||||||
|
XFixesDestroyRegion(dpy, border);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Window
|
static Window
|
||||||
|
@ -1484,14 +1497,18 @@ paint_preprocess(Display *dpy, win *list) {
|
||||||
// If the window is solid, we add the window region to the
|
// If the window is solid, we add the window region to the
|
||||||
// ignored region
|
// ignored region
|
||||||
if (WINDOW_SOLID == w->mode) {
|
if (WINDOW_SOLID == w->mode) {
|
||||||
if (!w->frame_opacity)
|
if (!w->frame_opacity) {
|
||||||
w->reg_ignore = win_get_region(dpy, w);
|
if (w->border_size)
|
||||||
else
|
w->reg_ignore = copy_region(dpy, w->border_size);
|
||||||
|
else
|
||||||
|
w->reg_ignore = win_get_region(dpy, w);
|
||||||
|
}
|
||||||
|
else {
|
||||||
w->reg_ignore = win_get_region_noframe(dpy, w);
|
w->reg_ignore = win_get_region_noframe(dpy, w);
|
||||||
|
if (w->border_size)
|
||||||
if (w->border_size)
|
XFixesIntersectRegion(dpy, w->reg_ignore, w->reg_ignore,
|
||||||
XFixesIntersectRegion(dpy, w->reg_ignore, w->reg_ignore,
|
w->border_size);
|
||||||
w->border_size);
|
}
|
||||||
|
|
||||||
if (last_reg_ignore)
|
if (last_reg_ignore)
|
||||||
XFixesUnionRegion(dpy, w->reg_ignore, w->reg_ignore,
|
XFixesUnionRegion(dpy, w->reg_ignore, w->reg_ignore,
|
||||||
|
@ -1555,33 +1572,59 @@ win_paint_win(Display *dpy, win *w, Picture tgt_buffer) {
|
||||||
tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
|
tgt_buffer, 0, 0, 0, 0, x, y, wid, hei);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsigned int t = w->top_width;
|
int t = w->top_width;
|
||||||
unsigned int l = w->left_width;
|
int l = w->left_width;
|
||||||
unsigned int b = w->bottom_width;
|
int b = w->bottom_width;
|
||||||
unsigned int r = w->right_width;
|
int r = w->right_width;
|
||||||
|
|
||||||
|
#define COMP_BDR(cx, cy, cwid, chei) \
|
||||||
|
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict, \
|
||||||
|
tgt_buffer, (cx), (cy), 0, 0, x + (cx), y + (cy), (cwid), (chei))
|
||||||
|
|
||||||
|
// The following complicated logic is requried because some broken
|
||||||
|
// window managers (I'm talking about you, Openbox!) that makes
|
||||||
|
// top_width + bottom_width > height in some cases.
|
||||||
|
|
||||||
// top
|
// top
|
||||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
COMP_BDR(0, 0, wid, min_i(t, hei));
|
||||||
tgt_buffer, 0, 0, 0, 0, x, y, wid, t);
|
|
||||||
|
|
||||||
// left
|
if (hei > t) {
|
||||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
int phei = min_i(hei - t, b);
|
||||||
tgt_buffer, 0, t, 0, t, x, y + t, l, hei - t);
|
|
||||||
|
|
||||||
// bottom
|
// bottom
|
||||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
if (phei) {
|
||||||
tgt_buffer, l, hei - b, l, hei - b, x + l, y + hei - b, wid - l - r, b);
|
assert(phei > 0);
|
||||||
|
COMP_BDR(0, hei - phei, wid, phei);
|
||||||
|
|
||||||
// right
|
phei = hei - t - phei;
|
||||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
if (phei) {
|
||||||
tgt_buffer, wid - r, t, wid - r, t, x + wid - r, y + t, r, hei - t);
|
assert(phei > 0);
|
||||||
|
// left
|
||||||
|
COMP_BDR(0, t, min_i(l, wid), phei);
|
||||||
|
|
||||||
// body
|
if (wid > l) {
|
||||||
XRenderComposite(dpy, op, w->picture, alpha_mask, tgt_buffer,
|
int pwid = min_i(wid - l, r);
|
||||||
l, t, l, t, x + l, y + t, wid - l - r, hei - t - b);
|
|
||||||
|
|
||||||
|
if (pwid) {
|
||||||
|
assert(pwid > 0);
|
||||||
|
// right
|
||||||
|
COMP_BDR(wid - pwid, t, pwid, phei);
|
||||||
|
|
||||||
|
pwid = wid - l - pwid;
|
||||||
|
if (pwid)
|
||||||
|
assert(pwid > 0);
|
||||||
|
// body
|
||||||
|
XRenderComposite(dpy, op, w->picture, alpha_mask,
|
||||||
|
tgt_buffer, l, t, 0, 0, x + l, y + t, pwid, phei);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef COMP_BDR
|
||||||
|
|
||||||
// Dimming the window if needed
|
// Dimming the window if needed
|
||||||
if (w->dim) {
|
if (w->dim) {
|
||||||
XRenderComposite(dpy, PictOpOver, dim_picture, None,
|
XRenderComposite(dpy, PictOpOver, dim_picture, None,
|
||||||
|
|
Loading…
Reference in New Issue