Fix many display problems with floating windows up against the window edge and borders of other windows and many off-by-one errors.

This commit is contained in:
Michael Grant 2025-11-10 23:07:06 +01:00
parent 31d0945059
commit 7194fdca38
2 changed files with 72 additions and 38 deletions

View File

@ -247,12 +247,15 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
u_int sy = w->sy; u_int sy = w->sy;
int sb_w, floating = 0; int sb_w, floating = 0;
floating = (wp->layout_cell == NULL);
sb_w = wp->scrollbar_style.width + sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad; wp->scrollbar_style.pad;
if (ctx->pane_status == PANE_STATUS_BOTTOM) if (ctx->pane_status == PANE_STATUS_BOTTOM)
sy--; sy--;
if (! floating) {
/* Outside the window? */ /* Outside the window? */
if (px > w->sx || py > sy) if (px > w->sx || py > sy)
return (0); return (0);
@ -260,16 +263,16 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp,
/* On the window border? */ /* On the window border? */
if (px == w->sx || py == sy) if (px == w->sx || py == sy)
return (1); return (1);
}
/* If checking a cell from a tiled pane, ignore floating panes /* If checking a cell from a tiled pane, ignore floating panes
* because 2 side-by-side or top-bottom panes share a border * because 2 side-by-side or top-bottom panes share a border
* which is used to do split coulering. Essentially treat all * which is used to do split colouring. Essentially treat all
* non-floating panes as being in a single z-index. * non-floating panes as being in a single z-index.
* *
* If checking a cell from a floating pane, only check cells * If checking a cell from a floating pane, only check cells
* from this floating pane, again, essentially only this z-index. * from this floating pane, again, essentially only this z-index.
*/ */
floating = (wp->layout_cell == NULL);
/* Check all the panes. */ /* Check all the panes. */
TAILQ_FOREACH(wp2, &w->z_index, zentry) { TAILQ_FOREACH(wp2, &w->z_index, zentry) {
@ -305,7 +308,7 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
int pane_status = ctx->pane_status; int pane_status = ctx->pane_status;
struct window *w = c->session->curw->window; struct window *w = c->session->curw->window;
u_int sx = w->sx, sy = w->sy; u_int sx = w->sx, sy = w->sy;
int borders = 0; int borders = 0, floating;
if (pane_status == PANE_STATUS_BOTTOM) if (pane_status == PANE_STATUS_BOTTOM)
sy--; sy--;
@ -314,6 +317,8 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
if (px > sx || py > sy) if (px > sx || py > sy)
return (CELL_OUTSIDE); return (CELL_OUTSIDE);
floating = (wp->layout_cell == NULL);
/* /*
* Construct a bitmask of whether the cells to the left (bit 8), right, * Construct a bitmask of whether the cells to the left (bit 8), right,
* top, and bottom (bit 1) of this cell are borders. * top, and bottom (bit 1) of this cell are borders.
@ -322,6 +327,7 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
* 8 + 4 * 8 + 4
* 1 * 1
*/ */
if (! floating) {
if (px == 0 || screen_redraw_cell_border(ctx, wp, px - 1, py)) if (px == 0 || screen_redraw_cell_border(ctx, wp, px - 1, py))
borders |= 8; borders |= 8;
if (px <= sx && screen_redraw_cell_border(ctx, wp, px + 1, py)) if (px <= sx && screen_redraw_cell_border(ctx, wp, px + 1, py))
@ -346,6 +352,30 @@ screen_redraw_type_of_cell(struct screen_redraw_ctx *ctx,
if (screen_redraw_cell_border(ctx, wp, px, py + 1)) if (screen_redraw_cell_border(ctx, wp, px, py + 1))
borders |= 1; borders |= 1;
} }
} else {
if (screen_redraw_cell_border(ctx, wp, px - 1, py))
borders |= 8;
if (px <= sx && screen_redraw_cell_border(ctx, wp, px + 1, py))
borders |= 4;
if (pane_status == PANE_STATUS_TOP) {
if (py != 0 &&
screen_redraw_cell_border(ctx, wp, px, py - 1))
borders |= 2;
if (screen_redraw_cell_border(ctx, wp, px, py + 1))
borders |= 1;
} else if (pane_status == PANE_STATUS_BOTTOM) {
if (screen_redraw_cell_border(ctx, wp, px, py - 1))
borders |= 2;
if (py != sy &&
screen_redraw_cell_border(ctx, wp, px, py + 1))
borders |= 1;
} else {
if (screen_redraw_cell_border(ctx, wp, px, py - 1))
borders |= 2;
if (screen_redraw_cell_border(ctx, wp, px, py + 1))
borders |= 1;
}
}
/* /*
* Figure out what kind of border this cell is. Only one bit set * Figure out what kind of border this cell is. Only one bit set
@ -399,7 +429,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, u_int px, u_int py,
if (px > sx || py > sy) if (px > sx || py > sy)
return (CELL_OUTSIDE); return (CELL_OUTSIDE);
/* Look through panes in z-index order starting with active pane. */ /* Find pane higest in z-index at this point. */
TAILQ_FOREACH(wp, &w->z_index, zentry) { TAILQ_FOREACH(wp, &w->z_index, zentry) {
sb_w = wp->scrollbar_style.width + sb_w = wp->scrollbar_style.width +
wp->scrollbar_style.pad; wp->scrollbar_style.pad;
@ -547,12 +577,13 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
expanded = format_expand_time(ft, fmt); expanded = format_expand_time(ft, fmt);
if (wp->sx < 4) if (wp->sx < 4)
wp->status_size = width = 0; width = 0;
else else
wp->status_size = width = wp->sx + sb_w - 2; width = wp->sx + sb_w - 2;
max_width = (int)w->sx - (wp->xoff + 2) - sb_w; max_width = (int)w->sx - (wp->xoff + 2) - sb_w;
if (max_width < 0) max_width = 0; if (max_width < 0) max_width = 0;
if (width > (u_int)max_width) width = (u_int)max_width; if (width > (u_int)max_width) width = (u_int)max_width;
wp->status_size = width;
memcpy(&old, &wp->status_screen, sizeof old); memcpy(&old, &wp->status_screen, sizeof old);
screen_init(&wp->status_screen, width, 1, 0); screen_init(&wp->status_screen, width, 1, 0);
@ -644,6 +675,7 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
if (ctx->statustop) if (ctx->statustop)
yoff += ctx->statuslines; yoff += ctx->statuslines;
vr = screen_redraw_get_visible_ranges(wp, x, yoff - ctx->oy, vr = screen_redraw_get_visible_ranges(wp, x, yoff - ctx->oy,
width); width);
@ -1039,7 +1071,9 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
bb = wp->yoff + wp->sy; bb = wp->yoff + wp->sy;
if (!found_self || if (!found_self ||
(wp->flags & PANE_MINIMISED) || (wp->flags & PANE_MINIMISED) ||
(py < tb || py > bb)) py < tb ||
(wp->layout_cell == NULL && py > bb) ||
(wp->layout_cell != NULL && py >= bb))
continue; continue;
/* Are scrollbars enabled? */ /* Are scrollbars enabled? */
@ -1068,7 +1102,7 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, u_int px,
falls inside of this range and left falls inside of this range and left
edge covers the left of range, edge covers the left of range,
then move px forward to right edge of wp. */ then move px forward to right edge of wp. */
else if (rb > vr.px[r] && else if (rb >= vr.px[r] &&
rb < vr.px[r] + vr.nx[r] && rb < vr.px[r] + vr.nx[r] &&
lb <= vr.px[r]) { lb <= vr.px[r]) {
vr.nx[r] = vr.nx[r] - (rb + 1 - vr.px[r]); vr.nx[r] = vr.nx[r] - (rb + 1 - vr.px[r]);

2
tty.c
View File

@ -2259,7 +2259,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
for (i = 0; i < OVERLAY_MAX_RANGES; i++) for (i = 0; i < OVERLAY_MAX_RANGES; i++)
vis += r.nx[i]; vis += r.nx[i];
if (vis < gcp->data.width || if (vis < gcp->data.width ||
vis2 < gcp->data.width) { vis2 < gcp->data.width) { /* xxxx check visible range */
tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width, tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width,
px, py, &ctx->defaults, ctx->palette); px, py, &ctx->defaults, ctx->palette);
return; return;