Switch menus also to be attached to the window instead of an overlay and

drawn as part of the client's scene. This means removing the popup menu.
This commit is contained in:
nicm
2026-07-14 19:07:03 +00:00
committed by tmux update bot
parent 1a02c9957c
commit ad6832e697
9 changed files with 567 additions and 381 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: screen-redraw.c,v 1.150 2026/07/09 07:32:58 nicm Exp $ */
/* $OpenBSD: screen-redraw.c,v 1.151 2026/07/14 19:07:03 nicm Exp $ */
/*
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -68,8 +68,9 @@ enum redraw_span_type {
REDRAW_SPAN_STATUS, /* pane status line */
REDRAW_SPAN_BORDER, /* pane border */
REDRAW_SPAN_SCROLLBAR, /* pane scrollbar */
REDRAW_SPAN_MENU, /* window menu */
};
#define REDRAW_SPAN_TYPES 6
#define REDRAW_SPAN_TYPES 7
/* Border connections to adjacent cells. */
#define REDRAW_BORDER_L 0x1
@@ -91,7 +92,8 @@ enum redraw_span_type {
#define REDRAW_PANE_STATUS 0x10
#define REDRAW_PANE_SCROLLBAR 0x20
#define REDRAW_STATUS 0x40
#define REDRAW_OVERLAY 0x80
#define REDRAW_MENU 0x80
#define REDRAW_OVERLAY 0x100
/* Draw everything. */
#define REDRAW_ALL 0x7fffffff
@@ -163,6 +165,15 @@ struct redraw_span_data {
/* Flags for this span. */
int flags;
} sb; /* pane scrollbar */
struct {
/* Menu this span belongs to. */
struct menu_data *md;
/* Position of span inside the menu. */
u_int px;
u_int py;
} m; /* menu */
};
};
@@ -251,6 +262,8 @@ redraw_flags_to_string(int flags)
strlcat(s, "pane-status ", sizeof s);
if (flags & REDRAW_PANE_SCROLLBAR)
strlcat(s, "scrollbar ", sizeof s);
if (flags & REDRAW_MENU)
strlcat(s, "menu ", sizeof s);
if (flags & REDRAW_OVERLAY)
strlcat(s, "overlay ", sizeof s);
if (REDRAW_IS_ALL(flags))
@@ -828,6 +841,34 @@ redraw_mark_two_pane_colours(struct redraw_build_ctx *bctx)
}
}
/* Mark the window menu above all panes. */
static void
redraw_mark_menu(struct redraw_build_ctx *bctx)
{
struct menu_data *md = bctx->w->menu;
struct redraw_build_cell *bc;
u_int px, py, x, y, sx, sy;
if (md == NULL)
return;
sx = menu_width(md);
sy = menu_height(md);
for (py = 0; py < sy; py++) {
for (px = 0; px < sx; px++) {
if (!redraw_window_to_scene(bctx, menu_x(md) + px,
menu_y(md) + py, &x, &y))
continue;
bc = redraw_get_build_cell(bctx, x, y);
memset(bc, 0, sizeof *bc);
bc->data.type = REDRAW_SPAN_MENU;
bc->data.m.md = md;
bc->data.m.px = px;
bc->data.m.py = py;
}
}
}
/* Return true if two adjacent build cells can be joined into one span. */
static int
redraw_compare_data(struct redraw_build_cell *a, struct redraw_build_cell *b)
@@ -874,6 +915,12 @@ redraw_compare_data(struct redraw_build_cell *a, struct redraw_build_cell *b)
ad->sb.flags != bd->sb.flags)
return (0);
return (1);
case REDRAW_SPAN_MENU:
if (ad->m.md != bd->m.md ||
ad->m.py != bd->m.py ||
ad->m.px + 1 != bd->m.px)
return (0);
return (1);
case REDRAW_SPAN_OUTSIDE:
case REDRAW_SPAN_EMPTY:
return (1);
@@ -908,6 +955,7 @@ redraw_build_cells(struct redraw_build_ctx *bctx)
TAILQ_FOREACH_REVERSE(wp, &w->z_index, window_panes_zindex, zentry)
redraw_mark_pane(bctx, wp);
redraw_mark_two_pane_colours(bctx);
redraw_mark_menu(bctx);
}
/*
@@ -1303,6 +1351,20 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
}
}
/* Draw a menu span. */
static void
redraw_draw_menu_span(struct redraw_draw_ctx *dctx,
struct redraw_span *span, u_int x, u_int y, u_int n)
{
struct redraw_scene *scene = dctx->scene;
struct tty *tty = &scene->c->tty;
struct screen *s = menu_screen(span->data.m.md);
u_int px;
px = span->data.m.px + (x - span->x);
tty_draw_line(tty, s, px, span->data.m.py, n, x, y, NULL);
}
/* Draw a span. */
static void
redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
@@ -1343,6 +1405,9 @@ redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
case REDRAW_SPAN_SCROLLBAR:
redraw_draw_scrollbar_span(dctx, span, x, y, n);
break;
case REDRAW_SPAN_MENU:
redraw_draw_menu_span(dctx, span, x, y, n);
break;
}
}
}
@@ -1434,6 +1499,10 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags)
if (~flags & REDRAW_PANE_SCROLLBAR)
continue;
break;
case REDRAW_SPAN_MENU:
if (~flags & REDRAW_MENU)
continue;
break;
default:
continue;
}
@@ -1445,6 +1514,26 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags)
}
}
/* Draw menu spans. */
static void
redraw_draw_menu_lines(struct redraw_draw_ctx *dctx)
{
struct redraw_scene *scene = dctx->scene;
struct redraw_line *line;
struct redraw_span *span;
u_int y, cy;
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;
TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry)
redraw_draw_span(dctx, span, cy);
}
}
/* Get line for pane status line. */
static int
redraw_pane_status_line(struct redraw_draw_ctx *dctx,
@@ -1620,6 +1709,8 @@ redraw_draw(struct client *c, struct window_pane *wp, int flags)
if (scene == NULL)
return;
redraw_set_draw_context(&dctx, scene);
if (w->menu != NULL)
menu_update(w->menu);
if (flags & (REDRAW_PANE_BORDER|REDRAW_PANE_STATUS)) {
TAILQ_FOREACH(loop, &scene->w->panes, entry) {
@@ -1686,6 +1777,8 @@ redraw_draw(struct client *c, struct window_pane *wp, int flags)
}
}
}
if (w->menu != NULL && (flags & REDRAW_MENU))
redraw_draw_menu_lines(&dctx);
if (flags & REDRAW_STATUS) {
lines = dctx.status_lines;
@@ -1766,6 +1859,10 @@ redraw_screen(struct client *c)
flags |= (REDRAW_STATUS|REDRAW_PANE_STATUS);
if (c->flags & CLIENT_REDRAWOVERLAY)
flags |= REDRAW_OVERLAY;
if (c->flags & CLIENT_REDRAWMENU)
flags |= REDRAW_MENU;
if (c->session->curw->window->menu != NULL)
flags |= REDRAW_MENU;
if (flags != 0)
redraw_draw(c, NULL, flags);
}
@@ -1776,6 +1873,8 @@ void
redraw_pane(struct client *c, struct window_pane *wp)
{
redraw_draw(c, wp, REDRAW_PANE|REDRAW_PANE_SCROLLBAR);
if (c->session->curw->window->menu != NULL)
redraw_draw(c, NULL, REDRAW_MENU);
}
/* Draw a pane's scrollbar. */