Add support in screen-write.c to properly display cmd output when there are floating panes on the screen.

This commit is contained in:
Michael Grant
2025-10-10 23:59:47 +01:00
parent 7634daa834
commit 5faf41b695
4 changed files with 173 additions and 62 deletions

View File

@@ -885,34 +885,41 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
}
}
struct visual_range {
u_int px;
u_int nx;
};
/* Construct ranges of line at px,py of width cells of base_wp that are
unobsructed. */
void
screen_redraw_get_visible_ranges(u_int px, u_int py, u_int width,
struct window_pane *base_wp, struct visible_range **vr_p,
int *vr_count_p) {
struct window_pane *wp;
struct window *w;
struct visible_range *vr;
int found_self, r, s;
int vr_len, vr_count;
static void
screen_redraw_get_visual_ranges(u_int px, u_int py, u_int width,
struct window_pane *base_wp, struct window *w,
struct visual_range **vr_p, int *vr_count_p) {
struct visual_range *vr;
int found_self, r, s;
int vr_len, vr_count;
struct window_pane *wp;
vr = xcalloc(4, sizeof(struct visual_range *));
vr_len = 4; // 4 initial slots
vr[0].px = px; // initialise first slot
/* Caller must call free(vr). */
vr = xcalloc(4, sizeof(struct visible_range *));
vr_len = 4;
vr[0].px = px;
vr[0].nx = width;
vr_count = 1;
if (base_wp == NULL) {
*vr_p = vr;
*vr_count_p = vr_count;
return;
}
w = base_wp->window;
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp == base_wp) { // wp == current pane
if (wp == base_wp) {
found_self = 1;
continue;
}
if (found_self && wp->layout_cell == NULL &&
!(wp->flags & PANE_MINIMISED) &&
(wp->yoff >= py && py <= wp->yoff + wp->sy)) {
(py >= wp->yoff && py <= wp->yoff + wp->sy)) {
for (r=0; r<vr_count; r++) {
/* if the left edge of wp
falls inside this range and right
@@ -920,19 +927,20 @@ screen_redraw_get_visual_ranges(u_int px, u_int py, u_int width,
then shrink nx */
if (wp->xoff > vr[r].px &&
wp->xoff < vr[r].px + vr[r].nx &&
wp->xoff + wp->sx > vr[r].px + vr[r].nx)
wp->xoff + wp->sx > vr[r].px + vr[r].nx) {
vr[r].nx = wp->xoff;
/* else if the right edge of wp
falls inside of this range and left
edge is less than the start of the range,
then move px forward */
else if (wp->xoff + wp->sx > vr[r].px &&
} else if (wp->xoff + wp->sx > vr[r].px &&
wp->xoff + wp->sx < vr[r].px + vr[r].nx &&
wp->xoff < vr[r].px + vr[r].nx)
vr[r].px = wp->xoff + wp->sx;
wp->xoff < vr[r].px) {
vr[r].px = vr[r].px + (wp->xoff + wp->sx);
vr[r].nx = vr[r].nx - (wp->xoff + wp->sx);
/* else if wp fully inside range
then split range into 2 ranges */
else if (wp->xoff > vr[r].px &&
} else if (wp->xoff > vr[r].px &&
wp->xoff + wp->sx < vr[r].px + vr[r].nx) {
/* make space */
if (vr_len == vr_count) {
@@ -946,7 +954,8 @@ screen_redraw_get_visual_ranges(u_int px, u_int py, u_int width,
}
vr[r].nx = wp->xoff;
vr[r+1].px = wp->xoff + wp->sx;
}
vr_count++;
} /* XXX what if it's completely obscured? */
}
}
}
@@ -965,7 +974,7 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
struct screen *s = wp->screen;
struct colour_palette *palette = &wp->palette;
struct grid_cell defaults;
struct visual_range *vr;
struct visible_range *vr;
int vr_count, r;
u_int i, j, top, x, y, width;
@@ -1009,12 +1018,15 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
__func__, c->name, wp->id, i, j, x, y, width);
screen_redraw_get_visual_ranges(x, y, width, wp, w, &vr, &vr_count);
/* Get visible ranges of line before we draw it. */
screen_redraw_get_visible_ranges(x, y, width, wp,
&vr, &vr_count);
tty_default_colours(&defaults, wp);
for (r=0; r<vr_count; r++)
tty_draw_line(tty, s, i, j, vr[r].nx, vr[r].px, y, &defaults, palette);
tty_draw_line(tty, s, i + vr[r].px, j,
vr[r].nx, vr[r].px, y, &defaults, palette);
free(vr);
}