From 7a3b7ae81263380c00f511846e7d07c9392f8730 Mon Sep 17 00:00:00 2001 From: nicm Date: Sat, 30 May 2026 16:10:13 +0000 Subject: [PATCH 1/4] Return empty ranges if line is below window. --- screen-redraw.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index 2bf0b9e2..f8a1a35d 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1131,17 +1131,8 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px, u_int lb, rb, tb, bb; u_int i, s; - if (px + width <= 0 || py < 0) { - if (r == NULL) { - if (sr.ranges == NULL) - sr.ranges = xcalloc(1, sizeof *sr.ranges); - sr.size = 1; - sr.used = 0; - return (&sr); - } - r->used = 0; - return (r); - } + if (px + width <= 0 || py < 0) + goto empty; if (px < 0) { px = 0; width += px; @@ -1160,6 +1151,8 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px, } w = base_wp->window; + if ((u_int)py >= w->sy) + goto empty; if (px + width > w->sx) width = w->sx - px; @@ -1271,6 +1264,17 @@ screen_redraw_get_visible_ranges(struct window_pane *base_wp, int px, } } return (r); + +empty: + if (r == NULL) { + if (sr.ranges == NULL) + sr.ranges = xcalloc(1, sizeof *sr.ranges); + sr.size = 1; + sr.used = 0; + return (&sr); + } + r->used = 0; + return (r); } /* Draw one pane. */ @@ -1300,7 +1304,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) * tty_x = window_x - ctx->ox * * window <-> tty (y-axis): - * woy = (ctx->statustop) ? ctx->statuslines : 0 + * woy = ctx->statustop ? ctx->statuslines : 0 * window_y = tty_y + ctx->oy - woy * tty_y = woy + window_y - ctx->oy * From e3ee2b327b7e7d0b35c1c4de9f4ca090bb174a01 Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 31 May 2026 20:41:07 +0000 Subject: [PATCH 2/4] Move back to starting position when pane is outside the window at all. --- window.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/window.c b/window.c index 6b834d2f..5af4f823 100644 --- a/window.c +++ b/window.c @@ -2126,7 +2126,7 @@ window_pane_floating_geometry(struct window *w, __unused struct window_pane *wp, u_int *out_x, u_int *out_y, u_int *out_sx, u_int *out_sy, struct cmdq_item *item, struct args *args, char **cause) { - u_int x, y, sx = w->sx / 2, sy = w->sy / 2; + u_int x, y, sx = w->sx / 2, sy = w->sy / 4; if (args_has(args, 'x')) { sx = args_percentage_and_expand(args, 'x', 0, USHRT_MAX, w->sx, @@ -2151,8 +2151,12 @@ window_pane_floating_geometry(struct window *w, __unused struct window_pane *wp, x = 4; else { x = w->last_new_pane_x + 4; - if (w->last_new_pane_x > w->sx) + if (x + sx >= w->sx) { + w->last_new_pane_x = 0; + w->last_new_pane_y = 0; x = 4; + y = 2; + } } w->last_new_pane_x = x; } @@ -2166,8 +2170,12 @@ window_pane_floating_geometry(struct window *w, __unused struct window_pane *wp, y = 2; else { y = w->last_new_pane_y + 2; - if (w->last_new_pane_y > w->sy) + if (y + sy >= w->sy) { + w->last_new_pane_x = 0; + w->last_new_pane_y = 0; + x = 4; y = 2; + } } w->last_new_pane_y = y; } From d876bb8cf3e24e4df389c7b6367723d3795e62fa Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 31 May 2026 21:08:23 +0000 Subject: [PATCH 3/4] When pane-border-indicators is set to "both" or "arrows", only draw arrows on the active floating pane and no other floating panes. Also there is no need to loop in screen_redraw_cell_border if only checking one pane. --- screen-redraw.c | 109 +++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 48 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index f8a1a35d..35e4b9ef 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -242,6 +242,34 @@ screen_redraw_pane_border(struct screen_redraw_ctx *ctx, struct window_pane *wp, return (SCREEN_REDRAW_OUTSIDE); } +/* Check a single cell position. */ +static int +screen_redraw_cell_border1(struct screen_redraw_ctx *ctx, int sb_pos, int sb_w, + struct window_pane *wp, int px, int py) +{ + if (sb_pos == PANE_SCROLLBARS_LEFT) { + if ((px < wp->xoff - 1 - sb_w || + px > wp->xoff + (int)wp->sx) && + (py < wp->yoff - 1 || + py > wp->yoff + (int)wp->sy)) + return (-1); + } else { /* PANE_SCROLLBARS_RIGHT or off. */ + if ((px < wp->xoff - 1 || + px > wp->xoff + (int)wp->sx + sb_w) && + (py < wp->yoff - 1 || + py > wp->yoff + (int)wp->sy)) + return (-1); + } + switch (screen_redraw_pane_border(ctx, wp, px, py)) { + case SCREEN_REDRAW_INSIDE: + return (0); + case SCREEN_REDRAW_OUTSIDE: + return (-1); + default: + return (1); + } +} + /* Check if a cell is on a border. */ static int screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp, @@ -250,7 +278,7 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp, struct client *c = ctx->c; struct window *w = c->session->curw->window; struct window_pane *wp2; - int sx = w->sx, sy = w->sy, sb_w, sb_pos, floating; + int sx = w->sx, sy = w->sy, sb_w, sb_pos, n; if (ctx->pane_scrollbars != 0) sb_pos = ctx->pane_scrollbars_pos; @@ -258,57 +286,34 @@ screen_redraw_cell_border(struct screen_redraw_ctx *ctx, struct window_pane *wp, sb_pos = 0; sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad; + /* For floating panes, only check the pane itself. */ + if (wp->flags & PANE_FLOATING) { + n = screen_redraw_cell_border1(ctx, sb_pos, sb_w, wp, px, py); + if (n == -1) + return (0); + return (n); + } + + /* Outside the window or on the window border? */ if (ctx->pane_status == PANE_STATUS_BOTTOM) sy--; - - floating = (wp->flags & PANE_FLOATING); - if (!floating) { - /* Outside the window? */ - if (px > sx || py > sy) - return (0); - - /* On the window border? */ - if (px == sx || py == sy) - return (1); - } + if (px > sx || py > sy) + return (0); + if (px == sx || py == sy) + return (1); /* * If checking a cell from a tiled pane, ignore floating panes because - * tqo side-by-side or top-bottom panes share a border which is used to + * two side-by-side or top-bottom panes share a border which is used to * do split colouring. Essentially, treat all tiled panes as being in a * single z-index. - * - * If checking a cell from a floating pane, only check cells from this - * floating pane, again, essentially only this z-index. */ - - /* Check all the panes. */ TAILQ_FOREACH(wp2, &w->z_index, zentry) { - if (!window_pane_visible(wp2) || - (!floating && (wp2->flags & PANE_FLOATING)) || - (floating && wp2 != wp)) + if (!window_pane_visible(wp2) || wp2->flags & PANE_FLOATING) continue; - if (sb_pos == PANE_SCROLLBARS_LEFT) { - if ((px < wp2->xoff - 1 - sb_w || - px > wp2->xoff + (int)wp2->sx) && - (py < wp2->yoff - 1 || - py > wp2->yoff + (int)wp2->sy)) - continue; - } else { /* PANE_SCROLLBARS_RIGHT or off. */ - if ((px < wp2->xoff - 1 || - px > wp2->xoff + (int)wp2->sx + sb_w) && - (py < wp2->yoff - 1 || - py > wp2->yoff + (int)wp2->sy)) - continue; - } - switch (screen_redraw_pane_border(ctx, wp2, px, py)) { - case SCREEN_REDRAW_INSIDE: - return (0); - case SCREEN_REDRAW_OUTSIDE: - break; - default: - return (1); - } + n = screen_redraw_cell_border1(ctx, sb_pos, sb_w, wp2, px, py); + if (n != -1) + return (n); } return (0); @@ -440,7 +445,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py, if (px > sx || py > sy) return (CELL_OUTSIDE); - /* Find pane higest in z-index at this point. */ + /* Find pane highest in z-index at this point. */ TAILQ_FOREACH(wp, &w->z_index, zentry) { if (wp->flags & PANE_FLOATING && (px >= sx || py >= sy)) { /* Clip floating panes to window. */ @@ -479,9 +484,10 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py, */ if (~wp->flags & PANE_FLOATING) tiled_only = 1; - do { /* Loop until back to wp == start.*/ - if (!window_pane_visible(wp) || - (tiled_only && (wp->flags & PANE_FLOATING))) + do { /* loop until back to wp == start */ + if (!window_pane_visible(wp)) + goto next; + if (tiled_only && (wp->flags & PANE_FLOATING)) goto next; *wpp = wp; @@ -492,7 +498,7 @@ screen_redraw_check_cell(struct screen_redraw_ctx *ctx, int px, int py, (py < wp->yoff - 1 || py > wp->yoff + (int)wp->sy)) goto next; - } else { /* PANE_SCROLLBARS_RIGHT or none. */ + } else { /* PANE_SCROLLBARS_RIGHT or none */ if ((px < wp->xoff - 1 || px > wp->xoff + (int)wp->sx + sb_w) && (py < wp->yoff - 1 || @@ -568,7 +574,7 @@ screen_redraw_check_is(struct screen_redraw_ctx *ctx, int px, int py, enum screen_redraw_border_type border; if (wp == NULL) - return (0); /* No active pane. */ + return (0); /* no active pane */ border = screen_redraw_pane_border(ctx, wp, px, py); if (border != SCREEN_REDRAW_INSIDE && border != SCREEN_REDRAW_OUTSIDE) return (1); @@ -914,6 +920,13 @@ screen_redraw_draw_border_arrows(struct screen_redraw_ctx *ctx, int i, if (i != wp->xoff + 1 && j != wp->yoff + 1) return; + if (wp != active) { + if (active->flags & PANE_FLOATING) + return; + if (wp->flags & PANE_FLOATING) + return; + } + value = options_get_number(oo, "pane-border-indicators"); if (value != PANE_BORDER_ARROWS && value != PANE_BORDER_BOTH) return; From a9721ea2682df1a2b73b3d32833b22372d0dd9e9 Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 31 May 2026 21:29:41 +0000 Subject: [PATCH 4/4] Only draw visible parts of numbers for display-panes. --- cmd-display-panes.c | 57 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/cmd-display-panes.c b/cmd-display-panes.c index cd688081..efa7c7e4 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -55,6 +55,27 @@ cmd_display_panes_args_parse(__unused struct args *args, __unused u_int idx, return (ARGS_PARSE_COMMANDS_OR_STRING); } +static void +cmd_display_panes_put(struct screen_redraw_ctx *ctx, + struct window_pane *wp, u_int cx, u_int cy, const char *buf, size_t len) +{ + struct client *c = ctx->c; + struct tty *tty = &c->tty; + struct visible_ranges *r; + struct visible_range *ri; + u_int i, j; + + r = screen_redraw_get_visible_ranges(wp, ctx->ox + cx, ctx->oy + cy, + len, NULL); + for (i = 0; i < r->used; i++) { + ri = &r->ranges[i]; + for (j = ri->px; j < ri->px + ri->nx; j++) { + tty_cursor(tty, j - ctx->ox, cy); + tty_putn(tty, &buf[j - ri->px], 1, 1); + } + } +} + static void cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp) @@ -66,6 +87,7 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, struct window *w = wp->window; struct grid_cell fgc, bgc; u_int pane, idx, px, py, i, j, xoff, yoff, sx, sy; + u_int cx, cy; int colour, active_colour; char buf[16], lbuf[16], rbuf[16], *ptr; size_t len, llen, rlen; @@ -147,13 +169,17 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL); if (sx >= len + llen + 1) { len += llen + 1; - tty_cursor(tty, xoff + px - len / 2, yoff + py); - tty_putn(tty, buf, len, len); - tty_putn(tty, " ", 1, 1); - tty_putn(tty, lbuf, llen, llen); + cx = xoff + px - len / 2; + cy = yoff + py; + cmd_display_panes_put(ctx, wp, cx, cy, buf, len); + cx += len; + cmd_display_panes_put(ctx, wp, cx, cy, " ", 1); + cx++; + cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen); } else { - tty_cursor(tty, xoff + px - len / 2, yoff + py); - tty_putn(tty, buf, len, len); + cx = xoff + px - len / 2; + cy = yoff + py; + cmd_display_panes_put(ctx, wp, cx, cy, buf, len); } goto out; } @@ -169,9 +195,11 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, for (j = 0; j < 5; j++) { for (i = px; i < px + 5; i++) { - tty_cursor(tty, xoff + i, yoff + py + j); - if (window_clock_table[idx][j][i - px]) - tty_putc(tty, ' '); + if (!window_clock_table[idx][j][i - px]) + continue; + cx = xoff + i; + cy = yoff + py + j; + cmd_display_panes_put(ctx, wp, cx, cy, " ", 1); } } px += 6; @@ -181,13 +209,14 @@ cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx, goto out; tty_attributes(tty, &fgc, &grid_default_cell, NULL, NULL); if (rlen != 0 && sx >= rlen) { - tty_cursor(tty, xoff + sx - rlen, yoff); - tty_putn(tty, rbuf, rlen, rlen); + cx = xoff + sx - rlen; + cy = yoff; + cmd_display_panes_put(ctx, wp, cx, cy, rbuf, rlen); } if (llen != 0) { - tty_cursor(tty, xoff + sx / 2 + len * 3 - llen - 1, - yoff + py + 5); - tty_putn(tty, lbuf, llen, llen); + cx = xoff + sx / 2 + len * 3 - llen - 1; + cy = yoff + py + 5; + cmd_display_panes_put(ctx, wp, cx, cy, lbuf, llen); } out: