render: fix csd border rendering glitch when width > 5px

CSD borders are always *at least* 5px. If url.border-width=0, those
5px are all fully transparent (and act as interactive resize handles).

As csd.border-width increases, the number of transparent pixels
decrease. Once csd.border-width >= 5, the border is fully opaque.

When csd.border-width > 5, then width of the border is (obviously)
more than 5px. But, when rendering the opaque part of the border, we
still used 5px for the invisible part, which caused some pixman
rectangles to have negative x/y coordinates.

This resulted in rendering glitches due to overflows in pixman when
rendering the borders.

The fix is to ensure the total border size is always at least, but
not *always* 5px. That is, set it to max(5, csd.border-width).

This patch also fixes an issue where the CSD borders were not
dimmed (like the titlebar) when the window looses input focus.

Closes #823
This commit is contained in:
Daniel Eklöf 2021-11-29 19:23:58 +01:00
parent 73a048f9d3
commit 3afe317e46
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 25 additions and 4 deletions

View file

@ -56,6 +56,9 @@
unrelated cells (https://codeberg.org/dnkl/foot/issues/816).
* OSC-8 URIs incorrectly being dropped when resizing the terminal
window with the alternate screen active.
* CSD border not being dimmed when window is not focused.
* Visual corruption with large CSD borders
(https://codeberg.org/dnkl/foot/issues/823).
### Security

View file

@ -1763,14 +1763,16 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
* The visible border.
*/
int bwidth = term->conf->csd.border_width; /* Full border size */
int vwidth = term->conf->csd.border_width_visible; /* Visibls size */
int bwidth = max(term->conf->csd.border_width,
term->conf->csd.border_width_visible); /* Full border size */
int vwidth = term->conf->csd.border_width_visible; /* Visibls size */
if (vwidth > 0) {
const struct config *conf = term->conf;
int x = 0, y = 0, w = 0, h = 0;
switch (surf_idx) {
case CSD_SURF_TOP:
case CSD_SURF_BOTTOM:
@ -1788,17 +1790,33 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx,
h = info->height;
break;
default:
break;
case CSD_SURF_TITLE:
case CSD_SURF_MINIMIZE:
case CSD_SURF_MAXIMIZE:
case CSD_SURF_CLOSE:
case CSD_SURF_COUNT:
BUG("unexpected CSD surface type");
}
xassert(x >= 0);
xassert(y >= 0);
xassert(w >= 0);
xassert(h >= 0);
xassert(x + w <= info->width);
xassert(y + h <= info->height);
uint32_t _color =
conf->csd.color.border_set ? conf->csd.color.border :
conf->csd.color.title_set ? conf->csd.color.title :
0xffu << 24 | term->conf->colors.fg;
if (!term->visual_focus)
_color = color_dim(term, _color);
uint16_t alpha = _color >> 24 | (_color >> 24 << 8);
pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha);
pixman_image_fill_rectangles(
PIXMAN_OP_SRC, buf->pix[0], &color, 1,
&(pixman_rectangle16_t){x, y, w, h});