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>
@@ -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);
}
}
@@ -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_spans *spans;
struct redraw_span *span;
enum redraw_phase phase;
u_int cy, yy, type;
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)
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);
}
}
}

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>
@@ -2328,7 +2328,7 @@ struct client {
int references;
int theme_colours[COLOUR_THEME_COUNT];
int theme_colours[COLOUR_THEME_COUNT];
void *pan_window;
u_int pan_ox;