Fix screen clearing issue to surgically clear around floating panes.

This commit is contained in:
Michael Grant
2026-03-08 17:11:55 +00:00
parent 8e6450c8fc
commit 14a934d412

View File

@@ -36,6 +36,7 @@ static int screen_write_overwrite(struct screen_write_ctx *,
struct grid_cell *, u_int); struct grid_cell *, u_int);
static int screen_write_combine(struct screen_write_ctx *, static int screen_write_combine(struct screen_write_ctx *,
const struct grid_cell *); const struct grid_cell *);
static int screen_write_pane_obscured(struct window_pane *);
struct screen_write_citem { struct screen_write_citem {
u_int x; u_int x;
@@ -1396,6 +1397,23 @@ screen_write_clearstartofline(struct screen_write_ctx *ctx, u_int bg)
screen_write_collect_insert(ctx, ci); screen_write_collect_insert(ctx, ci);
} }
/* Clear part of a line from px for nx columns. */
static void
screen_write_clearpartofline(struct screen_write_ctx *ctx, u_int px, u_int nx,
u_int bg)
{
struct screen_write_citem *ci = ctx->item;
if (nx == 0)
return;
ci->x = px;
ci->used = nx;
ci->type = CLEAR;
ci->bg = bg;
screen_write_collect_insert(ctx, ci);
}
/* Move cursor to px,py. */ /* Move cursor to px,py. */
void void
screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py, screen_write_cursormove(struct screen_write_ctx *ctx, int px, int py,
@@ -1582,6 +1600,9 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
struct grid *gd = s->grid; struct grid *gd = s->grid;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s); u_int sx = screen_size_x(s), sy = screen_size_y(s);
u_int y, i, xoff, yoff, cx_save, cy_save;
struct visible_ranges *r;
struct visible_range *ri;
#ifdef ENABLE_SIXEL #ifdef ENABLE_SIXEL
if (image_check_line(s, s->cy, sy - s->cy) && ctx->wp != NULL) if (image_check_line(s, s->cy, sy - s->cy) && ctx->wp != NULL)
@@ -1606,7 +1627,52 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1)); screen_write_collect_clear(ctx, s->cy + 1, sy - (s->cy + 1));
screen_write_collect_flush(ctx, 0, __func__); screen_write_collect_flush(ctx, 0, __func__);
if (! screen_write_pane_obscured(ctx->wp)) {
tty_write(tty_cmd_clearendofscreen, &ttyctx); tty_write(tty_cmd_clearendofscreen, &ttyctx);
return;
}
/* Can't just clear screen, must avoid floating windows. */
cx_save = s->cx;
cy_save = s->cy;
if (ctx->wp != NULL) {
xoff = ctx->wp->xoff;
yoff = ctx->wp->yoff;
} else {
xoff = 0;
yoff = 0;
}
/* First line: visible ranges from the current cursor to end. */
if (s->cx <= sx - 1) {
r = screen_redraw_get_visible_ranges(ctx->wp,
xoff + s->cx, yoff + s->cy, sx - s->cx, NULL);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
if (ri->nx == 0)
continue;
screen_write_clearpartofline(ctx,
ri->px - xoff, ri->nx, bg);
}
}
/* Remaining lines: visible ranges across the full width. */
for (y = s->cy + 1; y < sy; y++) {
screen_write_set_cursor(ctx, 0, y);
r = screen_redraw_get_visible_ranges(ctx->wp,
xoff, yoff + y, sx, NULL);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
if (ri->nx == 0)
continue;
screen_write_clearpartofline(ctx,
ri->px - xoff, ri->nx, bg);
}
}
screen_write_collect_flush(ctx, 0, __func__);
screen_write_set_cursor(ctx, cx_save, cy_save);
} }
/* Clear to start of screen. */ /* Clear to start of screen. */
@@ -1616,6 +1682,9 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx = screen_size_x(s); u_int sx = screen_size_x(s);
u_int y, i, xoff, yoff, cx_save, cy_save;
struct visible_ranges *r;
struct visible_range *ri;
#ifdef ENABLE_SIXEL #ifdef ENABLE_SIXEL
if (image_check_line(s, 0, s->cy - 1) && ctx->wp != NULL) if (image_check_line(s, 0, s->cy - 1) && ctx->wp != NULL)
@@ -1634,7 +1703,50 @@ screen_write_clearstartofscreen(struct screen_write_ctx *ctx, u_int bg)
screen_write_collect_clear(ctx, 0, s->cy); screen_write_collect_clear(ctx, 0, s->cy);
screen_write_collect_flush(ctx, 0, __func__); screen_write_collect_flush(ctx, 0, __func__);
if (! screen_write_pane_obscured(ctx->wp)) {
tty_write(tty_cmd_clearstartofscreen, &ttyctx); tty_write(tty_cmd_clearstartofscreen, &ttyctx);
return;
}
/* Can't just clear screen, must avoid floating windows. */
cx_save = s->cx;
cy_save = s->cy;
if (ctx->wp != NULL) {
xoff = ctx->wp->xoff;
yoff = ctx->wp->yoff;
} else {
xoff = 0;
yoff = 0;
}
/* Lines 0 to cy-1: visible ranges across the full width. */
for (y = 0; y < s->cy; y++) {
screen_write_set_cursor(ctx, 0, y);
r = screen_redraw_get_visible_ranges(ctx->wp,
xoff, yoff + y, sx, NULL);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
if (ri->nx == 0)
continue;
screen_write_clearpartofline(ctx,
ri->px - xoff, ri->nx, bg);
}
}
/* Last line: visible ranges from 0 to cursor (inclusive). */
screen_write_set_cursor(ctx, 0, s->cy);
r = screen_redraw_get_visible_ranges(ctx->wp,
xoff, yoff + cy_save, s->cx + 1, NULL);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
if (ri->nx == 0)
continue;
screen_write_clearpartofline(ctx, ri->px - xoff, ri->nx, bg);
}
screen_write_collect_flush(ctx, 0, __func__);
screen_write_set_cursor(ctx, cx_save, cy_save);
} }
/* Clear entire screen. */ /* Clear entire screen. */
@@ -1644,6 +1756,9 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s); u_int sx = screen_size_x(s), sy = screen_size_y(s);
u_int y, i, xoff, yoff, cx_save, cy_save;
struct visible_ranges *r;
struct visible_range *ri;
#ifdef ENABLE_SIXEL #ifdef ENABLE_SIXEL
if (image_free_all(s) && ctx->wp != NULL) if (image_free_all(s) && ctx->wp != NULL)
@@ -1662,7 +1777,38 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
grid_view_clear(s->grid, 0, 0, sx, sy, bg); grid_view_clear(s->grid, 0, 0, sx, sy, bg);
screen_write_collect_clear(ctx, 0, sy); screen_write_collect_clear(ctx, 0, sy);
if (! screen_write_pane_obscured(ctx->wp)) {
tty_write(tty_cmd_clearscreen, &ttyctx); tty_write(tty_cmd_clearscreen, &ttyctx);
return;
}
/* Can't just clear screen, must avoid floating windows. */
cx_save = s->cx;
cy_save = s->cy;
if (ctx->wp != NULL) {
xoff = ctx->wp->xoff;
yoff = ctx->wp->yoff;
} else {
xoff = 0;
yoff = 0;
}
for (y = 0; y < sy; y++) {
screen_write_set_cursor(ctx, 0, y);
r = screen_redraw_get_visible_ranges(ctx->wp,
xoff, yoff + y, sx, NULL);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
if (ri->nx == 0)
continue;
screen_write_clearpartofline(ctx,
ri->px - xoff, ri->nx, bg);
}
}
screen_write_collect_flush(ctx, 0, __func__);
screen_write_set_cursor(ctx, cx_save, cy_save);
} }
/* Clear entire history. */ /* Clear entire history. */