Do redraw as two phases for text and images.

This commit is contained in:
nicm
2026-10-14 10:34:14 +00:00
committed by tmux update bot
parent 126dea8828
commit 93e55bb86d
2 changed files with 134 additions and 87 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: screen-redraw.c,v 1.163 2026/10/02 12:48:52 nicm Exp $ */ /* $OpenBSD: screen-redraw.c,v 1.164 2026/10/14 10:34:14 nicm Exp $ */
/* /*
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -72,6 +72,13 @@ enum redraw_span_type {
}; };
#define REDRAW_SPAN_TYPES 7 #define REDRAW_SPAN_TYPES 7
/* Draw phases. */
enum redraw_phase {
REDRAW_TEXT,
REDRAW_IMAGES
};
#define REDRAW_PHASE_COUNT 2
/* Border connections to adjacent cells. */ /* Border connections to adjacent cells. */
#define REDRAW_BORDER_L 0x1 #define REDRAW_BORDER_L 0x1
#define REDRAW_BORDER_R 0x2 #define REDRAW_BORDER_R 0x2
@@ -1503,31 +1510,35 @@ redraw_draw_menu_span(struct redraw_draw_ctx *dctx,
/* Draw a span. */ /* Draw a span. */
static void static void
redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span, 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; struct redraw_span_data *data = &span->data;
enum redraw_span_type type = data->type; enum redraw_span_type type = data->type;
u_int width = span->width;
if (type == REDRAW_SPAN_STATUS && ~data->st.wp->flags & PANE_NEWSTATUS) if (type == REDRAW_SPAN_STATUS && ~data->st.wp->flags & PANE_NEWSTATUS)
return; return;
if (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE)
return;
switch (span->data.type) { switch (span->data.type) {
case REDRAW_SPAN_PANE: 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; break;
case REDRAW_SPAN_BORDER: case REDRAW_SPAN_BORDER:
case REDRAW_SPAN_EMPTY: case REDRAW_SPAN_EMPTY:
case REDRAW_SPAN_OUTSIDE: 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; break;
case REDRAW_SPAN_STATUS: 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; break;
case REDRAW_SPAN_SCROLLBAR: 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; break;
case REDRAW_SPAN_MENU: 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; break;
} }
} }
@@ -1541,6 +1552,7 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp,
struct redraw_line *line; struct redraw_line *line;
struct redraw_spans *spans; struct redraw_spans *spans;
struct redraw_span *span; struct redraw_span *span;
enum redraw_phase phase;
u_int cy; u_int cy;
int y, top, bottom; 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) if (bottom > (int)scene->sy)
bottom = scene->sy; bottom = scene->sy;
for (y = top; y < bottom; y++) { /* Draw each phase. */
line = &scene->lines[y]; for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
if (dctx->flags & REDRAW_STATUS_TOP) for (y = top; y < bottom; y++) {
cy = dctx->status_lines + y; line = &scene->lines[y];
else if (dctx->flags & REDRAW_STATUS_TOP)
cy = y; cy = dctx->status_lines + y;
if (flags & REDRAW_PANE) { else
spans = &line->spans[REDRAW_SPAN_PANE]; cy = y;
TAILQ_FOREACH(span, spans, entry) { if (flags & REDRAW_PANE) {
if (span->data.p.wp == wp) spans = &line->spans[REDRAW_SPAN_PANE];
redraw_draw_span(dctx, span, cy); TAILQ_FOREACH(span, spans, entry) {
} if (span->data.p.wp != wp)
} continue;
if (flags & REDRAW_PANE_SCROLLBAR) { redraw_draw_span(dctx, span, cy, phase);
spans = &line->spans[REDRAW_SPAN_SCROLLBAR]; }
TAILQ_FOREACH(span, spans, entry) { }
if (span->data.sb.wp == wp) if (phase == REDRAW_TEXT &&
redraw_draw_span(dctx, span, cy); (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. */ /* Draw lines. */
static void static void
redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags) 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_line *line;
struct redraw_spans *spans; struct redraw_spans *spans;
struct redraw_span *span; struct redraw_span *span;
enum redraw_phase phase;
u_int y, cy, type; u_int y, cy, type;
for (y = 0; y < scene->sy; y++) { /* Draw each phase. */
line = &scene->lines[y]; for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
if (dctx->flags & REDRAW_STATUS_TOP) for (y = 0; y < scene->sy; y++) {
cy = dctx->status_lines + y; line = &scene->lines[y];
else if (dctx->flags & REDRAW_STATUS_TOP)
cy = y; cy = dctx->status_lines + y;
for (type = 0; type < REDRAW_SPAN_TYPES; type++) { else
if (!REDRAW_IS_ALL(flags)) { cy = y;
switch (type) { for (type = 0; type < REDRAW_SPAN_TYPES; type++) {
case REDRAW_SPAN_PANE: if (!redraw_should_draw(type, flags, phase))
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:
continue; 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 else
cy = y; cy = y;
TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry) TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry)
redraw_draw_span(dctx, span, cy); redraw_draw_span(dctx, span, cy, REDRAW_TEXT);
} }
} }
@@ -2053,6 +2073,7 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
struct redraw_line *line; struct redraw_line *line;
struct redraw_spans *spans; struct redraw_spans *spans;
struct redraw_span *span; struct redraw_span *span;
enum redraw_phase phase;
u_int cy, yy, type; u_int cy, yy, type;
if (x >= scene->sx || y >= scene->sy) if (x >= scene->sx || y >= scene->sy)
@@ -2064,29 +2085,55 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
if (sx == 0 || sy == 0) if (sx == 0 || sy == 0)
return; 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++) { for (yy = y; yy < y + sy; yy++) {
line = &scene->lines[yy]; line = &scene->lines[yy];
if (dctx->flags & REDRAW_STATUS_TOP) if (dctx->flags & REDRAW_STATUS_TOP)
cy = dctx->status_lines + yy; cy = dctx->status_lines + yy;
else else
cy = yy; cy = yy;
for (type = 0; type < REDRAW_SPAN_TYPES; type++) { spans = &line->spans[REDRAW_SPAN_PANE];
spans = &line->spans[type]; TAILQ_FOREACH(span, spans, entry) {
TAILQ_FOREACH(span, spans, entry) { if (span->x >= x + sx)
if (span->x >= x + sx) continue;
continue; if (span->x + span->width <= x)
if (span->x + span->width <= x) continue;
continue; redraw_damage_draw_pane_prompt(dctx, span, cy);
if (type == REDRAW_SPAN_STATUS) { }
redraw_damage_refresh_status(dctx, spans = &line->spans[REDRAW_SPAN_STATUS];
span->data.st.wp); TAILQ_FOREACH(span, spans, entry) {
} if (span->x >= x + sx)
redraw_draw_span(dctx, span, cy); continue;
if (type == REDRAW_SPAN_PANE) { if (span->x + span->width <= x)
redraw_damage_draw_pane_prompt(dctx, continue;
span, cy); redraw_damage_refresh_status(dctx, span->data.st.wp);
} redraw_draw_span(dctx, span, cy, REDRAW_TEXT);
}
} }
} }
} }

4
tmux.h
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1460 2026/10/14 08:33:19 nicm Exp $ */ /* $OpenBSD: tmux.h,v 1.1461 2026/10/14 10:34:14 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2328,7 +2328,7 @@ struct client {
int references; int references;
int theme_colours[COLOUR_THEME_COUNT]; int theme_colours[COLOUR_THEME_COUNT];
void *pan_window; void *pan_window;
u_int pan_ox; u_int pan_ox;