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) {
|
||||
XRectangle r;
|
||||
|
||||
r.x = w->a.x + w->left_width;
|
||||
r.y = w->a.y + w->top_width;
|
||||
r.width = w->a.width;
|
||||
r.height = w->a.height;
|
||||
r.x = w->a.x + w->a.border_width + w->left_width;
|
||||
r.y = w->a.y + w->a.border_width + w->top_width;
|
||||
r.width = max_i(w->a.width - w->left_width - w->right_width, 0);
|
||||
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
|
||||
border_size(Display *dpy, win *w) {
|
||||
XserverRegion border;
|
||||
// Start with the window rectangular region
|
||||
XserverRegion fin = win_get_region(dpy, w);
|
||||
|
||||
/*
|
||||
* if window doesn't exist anymore, this will generate an error
|
||||
* as well as not generate a region. Perhaps a better XFixes
|
||||
* 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.
|
||||
*/
|
||||
// Only request for a bounding region if the window is shaped
|
||||
if (w->bounding_shaped) {
|
||||
/*
|
||||
* if window doesn't exist anymore, this will generate an error
|
||||
* as well as not generate a region. Perhaps a better XFixes
|
||||
* 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(
|
||||
dpy, w->id, WindowRegionBounding);
|
||||
XserverRegion border = XFixesCreateRegionFromWindow(
|
||||
dpy, w->id, WindowRegionBounding);
|
||||
|
||||
if (!border)
|
||||
return None;
|
||||
if (!border)
|
||||
return fin;
|
||||
|
||||
/* translate this */
|
||||
XFixesTranslateRegion(dpy, border,
|
||||
w->a.x + w->a.border_width,
|
||||
w->a.y + w->a.border_width);
|
||||
// Translate the region to the correct place
|
||||
XFixesTranslateRegion(dpy, border,
|
||||
w->a.x + 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
|
||||
|
@ -1484,14 +1497,18 @@ paint_preprocess(Display *dpy, win *list) {
|
|||
// If the window is solid, we add the window region to the
|
||||
// ignored region
|
||||
if (WINDOW_SOLID == w->mode) {
|
||||
if (!w->frame_opacity)
|
||||
w->reg_ignore = win_get_region(dpy, w);
|
||||
else
|
||||
if (!w->frame_opacity) {
|
||||
if (w->border_size)
|
||||
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);
|
||||
|
||||
if (w->border_size)
|
||||
XFixesIntersectRegion(dpy, w->reg_ignore, w->reg_ignore,
|
||||
w->border_size);
|
||||
if (w->border_size)
|
||||
XFixesIntersectRegion(dpy, w->reg_ignore, w->reg_ignore,
|
||||
w->border_size);
|
||||
}
|
||||
|
||||
if (last_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);
|
||||
}
|
||||
else {
|
||||
unsigned int t = w->top_width;
|
||||
unsigned int l = w->left_width;
|
||||
unsigned int b = w->bottom_width;
|
||||
unsigned int r = w->right_width;
|
||||
int t = w->top_width;
|
||||
int l = w->left_width;
|
||||
int b = w->bottom_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
|
||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
||||
tgt_buffer, 0, 0, 0, 0, x, y, wid, t);
|
||||
COMP_BDR(0, 0, wid, min_i(t, hei));
|
||||
|
||||
// left
|
||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
||||
tgt_buffer, 0, t, 0, t, x, y + t, l, hei - t);
|
||||
if (hei > t) {
|
||||
int phei = min_i(hei - t, b);
|
||||
|
||||
// bottom
|
||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
||||
tgt_buffer, l, hei - b, l, hei - b, x + l, y + hei - b, wid - l - r, b);
|
||||
// bottom
|
||||
if (phei) {
|
||||
assert(phei > 0);
|
||||
COMP_BDR(0, hei - phei, wid, phei);
|
||||
|
||||
// right
|
||||
XRenderComposite(dpy, PictOpOver, w->picture, w->frame_alpha_pict,
|
||||
tgt_buffer, wid - r, t, wid - r, t, x + wid - r, y + t, r, hei - t);
|
||||
phei = hei - t - phei;
|
||||
if (phei) {
|
||||
assert(phei > 0);
|
||||
// left
|
||||
COMP_BDR(0, t, min_i(l, wid), phei);
|
||||
|
||||
// body
|
||||
XRenderComposite(dpy, op, w->picture, alpha_mask, tgt_buffer,
|
||||
l, t, l, t, x + l, y + t, wid - l - r, hei - t - b);
|
||||
if (wid > l) {
|
||||
int pwid = min_i(wid - l, r);
|
||||
|
||||
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
|
||||
if (w->dim) {
|
||||
XRenderComposite(dpy, PictOpOver, dim_picture, None,
|
||||
|
|
Loading…
Reference in New Issue