From 464f404b85bc30db54d3570a789fad6adfbf9721 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Wed, 14 Oct 2026 11:33:16 +0100 Subject: [PATCH] Two phases for redraw. --- screen-redraw.c | 215 +++++++++++++++++++++++++++++------------------- tmux.h | 2 +- 2 files changed, 132 insertions(+), 85 deletions(-) diff --git a/screen-redraw.c b/screen-redraw.c index b50b6df65..ca4a4c3f3 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -72,6 +72,13 @@ enum redraw_span_type { }; #define REDRAW_SPAN_TYPES 7 +/* Draw phases. */ +enum redraw_phase { + REDRAW_TEXT, + REDRAW_IMAGES +}; +#define REDRAW_PHASE_COUNT 2 + /* Border connections to adjacent cells. */ #define REDRAW_BORDER_L 0x1 #define REDRAW_BORDER_R 0x2 @@ -1503,31 +1510,35 @@ redraw_draw_menu_span(struct redraw_draw_ctx *dctx, /* Draw a span. */ static void redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span, - u_int y) + u_int y, enum redraw_phase phase) { struct redraw_span_data *data = &span->data; enum redraw_span_type type = data->type; + u_int width = span->width; if (type == REDRAW_SPAN_STATUS && ~data->st.wp->flags & PANE_NEWSTATUS) return; + if (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE) + return; switch (span->data.type) { case REDRAW_SPAN_PANE: - redraw_draw_pane_span(dctx, span, span->x, y, span->width); + if (phase == REDRAW_TEXT) + redraw_draw_pane_span(dctx, span, span->x, y, width); break; case REDRAW_SPAN_BORDER: case REDRAW_SPAN_EMPTY: case REDRAW_SPAN_OUTSIDE: - redraw_draw_border_span(dctx, span, span->x, y, span->width); + redraw_draw_border_span(dctx, span, span->x, y, width); break; case REDRAW_SPAN_STATUS: - redraw_draw_status_span(dctx, span, span->x, y, span->width); + redraw_draw_status_span(dctx, span, span->x, y, width); break; case REDRAW_SPAN_SCROLLBAR: - redraw_draw_scrollbar_span(dctx, span, span->x, y, span->width); + redraw_draw_scrollbar_span(dctx, span, span->x, y, width); break; case REDRAW_SPAN_MENU: - redraw_draw_menu_span(dctx, span, span->x, y, span->width); + redraw_draw_menu_span(dctx, span, span->x, y, width); break; } } @@ -1541,6 +1552,7 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp, struct redraw_line *line; struct redraw_spans *spans; struct redraw_span *span; + enum redraw_phase phase; u_int cy; int y, top, bottom; @@ -1553,29 +1565,65 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp, if (bottom > (int)scene->sy) bottom = scene->sy; - for (y = top; y < bottom; y++) { - line = &scene->lines[y]; - if (dctx->flags & REDRAW_STATUS_TOP) - cy = dctx->status_lines + y; - else - cy = y; - if (flags & REDRAW_PANE) { - spans = &line->spans[REDRAW_SPAN_PANE]; - TAILQ_FOREACH(span, spans, entry) { - if (span->data.p.wp == wp) - redraw_draw_span(dctx, span, cy); - } - } - if (flags & REDRAW_PANE_SCROLLBAR) { - spans = &line->spans[REDRAW_SPAN_SCROLLBAR]; - TAILQ_FOREACH(span, spans, entry) { - if (span->data.sb.wp == wp) - redraw_draw_span(dctx, span, cy); + /* Draw each phase. */ + for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) { + for (y = top; y < bottom; y++) { + line = &scene->lines[y]; + if (dctx->flags & REDRAW_STATUS_TOP) + cy = dctx->status_lines + y; + else + cy = y; + if (flags & REDRAW_PANE) { + spans = &line->spans[REDRAW_SPAN_PANE]; + TAILQ_FOREACH(span, spans, entry) { + if (span->data.p.wp != wp) + continue; + redraw_draw_span(dctx, span, cy, phase); + } + } + if (phase == REDRAW_TEXT && + (flags & REDRAW_PANE_SCROLLBAR)) { + spans = &line->spans[REDRAW_SPAN_SCROLLBAR]; + TAILQ_FOREACH(span, spans, entry) { + if (span->data.sb.wp != wp) + continue; + redraw_draw_span(dctx, span, cy, phase); + } } } } } +/* Return whether to draw a span type in this phase for these flags. */ +static int +redraw_should_draw(enum redraw_span_type type, int flags, + enum redraw_phase phase) +{ + if (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE) + return (0); + if (REDRAW_IS_ALL(flags)) + return (1); + + switch (type) { + case REDRAW_SPAN_PANE: + return (flags & REDRAW_PANE); + case REDRAW_SPAN_OUTSIDE: + return (flags & REDRAW_OUTSIDE); + case REDRAW_SPAN_EMPTY: + return (flags & REDRAW_EMPTY); + case REDRAW_SPAN_BORDER: + return (flags & REDRAW_PANE_BORDER); + case REDRAW_SPAN_STATUS: + return (flags & REDRAW_PANE_STATUS); + case REDRAW_SPAN_SCROLLBAR: + return (flags & REDRAW_PANE_SCROLLBAR); + case REDRAW_SPAN_MENU: + return (flags & REDRAW_MENU); + default: + return (0); + } +} + /* Draw lines. */ static void redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags) @@ -1584,52 +1632,24 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags) struct redraw_line *line; struct redraw_spans *spans; struct redraw_span *span; + enum redraw_phase phase; u_int y, cy, type; - for (y = 0; y < scene->sy; y++) { - line = &scene->lines[y]; - if (dctx->flags & REDRAW_STATUS_TOP) - cy = dctx->status_lines + y; - else - cy = y; - for (type = 0; type < REDRAW_SPAN_TYPES; type++) { - if (!REDRAW_IS_ALL(flags)) { - switch (type) { - case REDRAW_SPAN_PANE: - if (~flags & REDRAW_PANE) - continue; - break; - case REDRAW_SPAN_OUTSIDE: - if (~flags & REDRAW_OUTSIDE) - continue; - break; - case REDRAW_SPAN_EMPTY: - if (~flags & REDRAW_EMPTY) - continue; - break; - case REDRAW_SPAN_BORDER: - if (~flags & REDRAW_PANE_BORDER) - continue; - break; - case REDRAW_SPAN_STATUS: - if (~flags & REDRAW_PANE_STATUS) - continue; - break; - case REDRAW_SPAN_SCROLLBAR: - if (~flags & REDRAW_PANE_SCROLLBAR) - continue; - break; - case REDRAW_SPAN_MENU: - if (~flags & REDRAW_MENU) - continue; - break; - default: + /* Draw each phase. */ + for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) { + for (y = 0; y < scene->sy; y++) { + line = &scene->lines[y]; + if (dctx->flags & REDRAW_STATUS_TOP) + cy = dctx->status_lines + y; + else + cy = y; + for (type = 0; type < REDRAW_SPAN_TYPES; type++) { + if (!redraw_should_draw(type, flags, phase)) continue; - } + spans = &line->spans[type]; + TAILQ_FOREACH(span, spans, entry) + redraw_draw_span(dctx, span, cy, phase); } - spans = &line->spans[type]; - TAILQ_FOREACH(span, spans, entry) - redraw_draw_span(dctx, span, cy); } } } @@ -1650,7 +1670,7 @@ redraw_draw_menu_lines(struct redraw_draw_ctx *dctx) else cy = y; TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry) - redraw_draw_span(dctx, span, cy); + redraw_draw_span(dctx, span, cy, REDRAW_TEXT); } } @@ -2052,6 +2072,7 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y, struct redraw_line *line; struct redraw_spans *spans; struct redraw_span *span; + enum redraw_phase phase; u_int cy, yy, type; if (x >= scene->sx || y >= scene->sy) @@ -2063,29 +2084,55 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y, if (sx == 0 || sy == 0) return; + /* Draw each phase in the damaged spans. */ + for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) { + for (yy = y; yy < y + sy; yy++) { + line = &scene->lines[yy]; + if (dctx->flags & REDRAW_STATUS_TOP) + cy = dctx->status_lines + yy; + else + cy = yy; + for (type = 0; type < REDRAW_SPAN_TYPES; type++) { + if (phase != REDRAW_TEXT && + type != REDRAW_SPAN_PANE) + continue; + if (type == REDRAW_SPAN_STATUS) + continue; + spans = &line->spans[type]; + TAILQ_FOREACH(span, spans, entry) { + if (span->x >= x + sx) + continue; + if (span->x + span->width <= x) + continue; + redraw_draw_span(dctx, span, cy, phase); + } + } + } + } + + /* Draw prompts and pane status lines last. */ for (yy = y; yy < y + sy; yy++) { line = &scene->lines[yy]; if (dctx->flags & REDRAW_STATUS_TOP) cy = dctx->status_lines + yy; else cy = yy; - for (type = 0; type < REDRAW_SPAN_TYPES; type++) { - spans = &line->spans[type]; - TAILQ_FOREACH(span, spans, entry) { - if (span->x >= x + sx) - continue; - if (span->x + span->width <= x) - continue; - if (type == REDRAW_SPAN_STATUS) { - redraw_damage_refresh_status(dctx, - span->data.st.wp); - } - redraw_draw_span(dctx, span, cy); - if (type == REDRAW_SPAN_PANE) { - redraw_damage_draw_pane_prompt(dctx, - span, cy); - } - } + spans = &line->spans[REDRAW_SPAN_PANE]; + TAILQ_FOREACH(span, spans, entry) { + if (span->x >= x + sx) + continue; + if (span->x + span->width <= x) + continue; + redraw_damage_draw_pane_prompt(dctx, span, cy); + } + spans = &line->spans[REDRAW_SPAN_STATUS]; + TAILQ_FOREACH(span, spans, entry) { + if (span->x >= x + sx) + continue; + if (span->x + span->width <= x) + continue; + redraw_damage_refresh_status(dctx, span->data.st.wp); + redraw_draw_span(dctx, span, cy, REDRAW_TEXT); } } } diff --git a/tmux.h b/tmux.h index 7c86555e1..6e51357cf 100644 --- a/tmux.h +++ b/tmux.h @@ -2352,7 +2352,7 @@ struct client { int references; - int theme_colours[COLOUR_THEME_COUNT]; + int theme_colours[COLOUR_THEME_COUNT]; void *pan_window; u_int pan_ox;