Fix dispay bugs where the cursor was on a line that had 2 visible ranges because it was partially obscured by a floating pane.

This commit is contained in:
Michael Grant
2026-03-18 09:38:17 +00:00
parent ab0081294c
commit 0d195698f8
2 changed files with 77 additions and 18 deletions

View File

@@ -1128,6 +1128,7 @@ screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg); grid_view_insert_cells(s->grid, s->cx, s->cy, nx, bg);
@@ -1161,6 +1162,7 @@ screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx, u_int bg)
screen_write_initctx(ctx, &ttyctx, 0); screen_write_initctx(ctx, &ttyctx, 0);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg); grid_view_delete_cells(s->grid, s->cx, s->cy, nx, bg);
@@ -1230,6 +1232,7 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_insert_lines(gd, s->cy, ny, bg); grid_view_insert_lines(gd, s->cy, ny, bg);
@@ -1246,6 +1249,9 @@ screen_write_insertline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
log_debug("%s: obscured=%d for pane %%%u", __func__,
ttyctx.obscured, ctx->wp != NULL ? ctx->wp->id : 0);
if (s->cy < s->rupper || s->cy > s->rlower) if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_insert_lines(gd, s->cy, ny, bg); grid_view_insert_lines(gd, s->cy, ny, bg);
@@ -1283,6 +1289,7 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
grid_view_delete_lines(gd, s->cy, ny, bg); grid_view_delete_lines(gd, s->cy, ny, bg);
@@ -1299,6 +1306,9 @@ screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny, u_int bg)
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
log_debug("%s: obscured=%d for pane %%%u", __func__,
ttyctx.obscured, ctx->wp != NULL ? ctx->wp->id : 0);
if (s->cy < s->rupper || s->cy > s->rlower) if (s->cy < s->rupper || s->cy > s->rlower)
grid_view_delete_lines(gd, s->cy, ny, bg); grid_view_delete_lines(gd, s->cy, ny, bg);
@@ -1570,6 +1580,7 @@ screen_write_scrolldown(struct screen_write_ctx *ctx, u_int lines, u_int bg)
screen_write_initctx(ctx, &ttyctx, 1); screen_write_initctx(ctx, &ttyctx, 1);
ttyctx.bg = bg; ttyctx.bg = bg;
ttyctx.obscured = screen_write_pane_obscured(ctx->wp);
if (lines == 0) if (lines == 0)
lines = 1; lines = 1;
@@ -1928,8 +1939,11 @@ screen_write_collect_clear(struct screen_write_ctx *ctx, u_int y, u_int n)
struct screen_write_cline *cl; struct screen_write_cline *cl;
u_int i; u_int i;
log_debug("%s: clearing rows %u..%u", __func__, y, y + n - 1);
for (i = y; i < y + n; i++) { for (i = y; i < y + n; i++) {
cl = &ctx->s->write_list[i]; cl = &ctx->s->write_list[i];
if (!TAILQ_EMPTY(&cl->items))
log_debug("%s: row %u had items!", __func__, i);
TAILQ_CONCAT(&screen_write_citem_freelist, &cl->items, entry); TAILQ_CONCAT(&screen_write_citem_freelist, &cl->items, entry);
} }
} }
@@ -1944,8 +1958,8 @@ screen_write_collect_scroll(struct screen_write_ctx *ctx, u_int bg)
char *saved; char *saved;
struct screen_write_citem *ci; struct screen_write_citem *ci;
log_debug("%s: at %u,%u (region %u-%u)", __func__, s->cx, s->cy, log_debug("%s: at %u,%u (region %u-%u) cy=%u", __func__, s->cx, s->cy,
s->rupper, s->rlower); s->rupper, s->rlower, s->cy);
screen_write_collect_clear(ctx, s->rupper, 1); screen_write_collect_clear(ctx, s->rupper, 1);
saved = ctx->s->write_list[s->rupper].data; saved = ctx->s->write_list[s->rupper].data;
@@ -2012,6 +2026,7 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
struct screen_write_cline *cl; struct screen_write_cline *cl;
u_int y, cx, cy, last, items = 0, i; u_int y, cx, cy, last, items = 0, i;
u_int wr_start, wr_end, wr_length, wsx, wsy; u_int wr_start, wr_end, wr_length, wsx, wsy;
int written;
int r_start, r_end, ci_start, ci_end; int r_start, r_end, ci_start, ci_end;
int xoff, yoff; int xoff, yoff;
struct tty_ctx ttyctx; struct tty_ctx ttyctx;
@@ -2083,6 +2098,16 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
NULL); NULL);
last = UINT_MAX; last = UINT_MAX;
if (y == (u_int)s->cy || !TAILQ_EMPTY(&cl->items)) {
u_int dbg_cnt = 0;
struct screen_write_citem *dbg_ci;
TAILQ_FOREACH(dbg_ci, &cl->items, entry) dbg_cnt++;
log_debug("%s: row y=%u has %u items (wp_xoff=%d yoff=%d wsx=%u)",
__func__, y, dbg_cnt,
wp ? (int)wp->xoff : -1,
wp ? (int)wp->yoff : -1,
wsx);
}
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) { TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
log_debug("collect list: x=%u (last %u), y=%u, used=%u", log_debug("collect list: x=%u (last %u), y=%u, used=%u",
ci->x, last, y, ci->used); ci->x, last, y, ci->used);
@@ -2091,6 +2116,7 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
ci->x, last); ci->x, last);
} }
wr_length = 0; wr_length = 0;
written = 0;
for (i = 0; i < r->used; i++) { for (i = 0; i < r->used; i++) {
ri = &r->ranges[i]; ri = &r->ranges[i];
if (ri->nx == 0) continue; if (ri->nx == 0) continue;
@@ -2133,10 +2159,12 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
tty_write(tty_cmd_cells, &ttyctx); tty_write(tty_cmd_cells, &ttyctx);
} }
items++; items++;
written = 1;
}
if (written) {
last = ci->x;
TAILQ_REMOVE(&cl->items, ci, entry); TAILQ_REMOVE(&cl->items, ci, entry);
screen_write_free_citem(ci); screen_write_free_citem(ci);
last = ci->x;
} }
} }
} }

51
tty.c
View File

@@ -1098,8 +1098,8 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
log_debug("%s: %s orlower=%u orupper=%u sy=%u large=%d", __func__, log_debug("%s: %s orlower=%u orupper=%u sy=%u large=%d", __func__,
c->name, ctx->orlower, ctx->orupper, ctx->sy, c->name, ctx->orlower, ctx->orupper, ctx->sy,
tty_large_region(tty, ctx)); tty_large_region(tty, ctx));
if (tty_large_region(tty, ctx)) { if (tty_large_region(tty, ctx) && !ctx->obscured) {
log_debug("%s: %s large redraw", __func__, c->name); log_debug("%s: %s large region redraw", __func__, c->name);
ctx->redraw_cb(ctx); ctx->redraw_cb(ctx);
return; return;
} }
@@ -1421,14 +1421,36 @@ tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
if (!ctx->bigger) { if (!ctx->bigger) {
if (wp) { if (wp) {
r = tty_check_overlay_range(tty, 0, ctx->yoff + py, nx); if (ctx->obscured) {
/*
* Floating pane is present: use physical
* coordinates and clip to visible ranges to
* avoid drawing over the floating pane.
*/
r = tty_check_overlay_range(tty, ctx->xoff,
ctx->yoff + py, nx);
r = screen_redraw_get_visible_ranges(wp,
ctx->xoff, ctx->yoff + py, nx, r);
for (i = 0; i < r->used; i++) { for (i = 0; i < r->used; i++) {
ri = &r->ranges[i]; ri = &r->ranges[i];
if (ri->nx == 0) continue; if (ri->nx == 0) continue;
tty_draw_line(tty, s, ri->px, py, ri->nx, tty_draw_line(tty, s,
ctx->xoff + ri->px, ctx->yoff + py, ri->px - ctx->xoff, py, ri->nx,
ri->px, ctx->yoff + py,
&ctx->defaults, ctx->palette); &ctx->defaults, ctx->palette);
} }
} else {
r = tty_check_overlay_range(tty, 0,
ctx->yoff + py, nx);
for (i = 0; i < r->used; i++) {
ri = &r->ranges[i];
if (ri->nx == 0) continue;
tty_draw_line(tty, s, ri->px, py,
ri->nx, ctx->xoff + ri->px,
ctx->yoff + py,
&ctx->defaults, ctx->palette);
}
}
} else { } else {
tty_draw_line(tty, s, 0, py, nx, ctx->xoff, tty_draw_line(tty, s, 0, py, nx, ctx->xoff,
ctx->yoff + py, &ctx->defaults, ctx->palette); ctx->yoff + py, &ctx->defaults, ctx->palette);
@@ -1664,7 +1686,8 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
tty_fake_bce(tty, &ctx->defaults, ctx->bg) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_ICH) && (!tty_term_has(tty->term, TTYC_ICH) &&
!tty_term_has(tty->term, TTYC_ICH1)) || !tty_term_has(tty->term, TTYC_ICH1)) ||
c->overlay_check != NULL) { c->overlay_check != NULL ||
ctx->obscured) {
tty_draw_pane(tty, ctx, ctx->ocy); tty_draw_pane(tty, ctx, ctx->ocy);
return; return;
} }
@@ -1687,7 +1710,8 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
tty_fake_bce(tty, &ctx->defaults, ctx->bg) || tty_fake_bce(tty, &ctx->defaults, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_DCH) && (!tty_term_has(tty->term, TTYC_DCH) &&
!tty_term_has(tty->term, TTYC_DCH1)) || !tty_term_has(tty->term, TTYC_DCH1)) ||
c->overlay_check != NULL) { c->overlay_check != NULL ||
ctx->obscured) {
tty_draw_pane(tty, ctx, ctx->ocy); tty_draw_pane(tty, ctx, ctx->ocy);
return; return;
} }
@@ -1721,7 +1745,8 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
!tty_term_has(tty->term, TTYC_IL1) || !tty_term_has(tty->term, TTYC_IL1) ||
ctx->sx == 1 || ctx->sx == 1 ||
ctx->sy == 1 || ctx->sy == 1 ||
c->overlay_check != NULL) { c->overlay_check != NULL ||
ctx->obscured) {
tty_redraw_region(tty, ctx); tty_redraw_region(tty, ctx);
return; return;
} }
@@ -1749,7 +1774,8 @@ tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
!tty_term_has(tty->term, TTYC_DL1) || !tty_term_has(tty->term, TTYC_DL1) ||
ctx->sx == 1 || ctx->sx == 1 ||
ctx->sy == 1 || ctx->sy == 1 ||
c->overlay_check != NULL) { c->overlay_check != NULL ||
ctx->obscured) {
tty_redraw_region(tty, ctx); tty_redraw_region(tty, ctx);
return; return;
} }
@@ -1925,7 +1951,8 @@ tty_cmd_scrolldown(struct tty *tty, const struct tty_ctx *ctx)
!tty_term_has(tty->term, TTYC_RIN)) || !tty_term_has(tty->term, TTYC_RIN)) ||
ctx->sx == 1 || ctx->sx == 1 ||
ctx->sy == 1 || ctx->sy == 1 ||
c->overlay_check != NULL) { c->overlay_check != NULL ||
ctx->obscured) {
tty_redraw_region(tty, ctx); tty_redraw_region(tty, ctx);
return; return;
} }
@@ -2257,6 +2284,10 @@ tty_cell(struct tty *tty, const struct grid_cell *gc,
if (gc->flags & GRID_FLAG_PADDING) if (gc->flags & GRID_FLAG_PADDING)
return; return;
/* Check if character is covered by overlay/floating pane. */
if (!tty_check_overlay(tty, tty->cx, tty->cy))
return; /* Character obscured by floating pane. */
/* Check the output codeset and apply attributes. */ /* Check the output codeset and apply attributes. */
gcp = tty_check_codeset(tty, gc); gcp = tty_check_codeset(tty, gc);
tty_attributes(tty, gcp, defaults, palette, hl); tty_attributes(tty, gcp, defaults, palette, hl);