Add support for borderless menus, like panes. GitHub issue 5447 from harikp2002

at gmail dot com.
This commit is contained in:
nicm
2026-09-21 12:14:32 +00:00
committed by tmux update bot
parent e361b8f8ff
commit dda0e4d489
5 changed files with 77 additions and 47 deletions

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: cmd-display-menu.c,v 1.54 2026/09/21 10:22:31 nicm Exp $ */ /* $OpenBSD: cmd-display-menu.c,v 1.55 2026/09/21 12:14:32 nicm Exp $ */
/* /*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -286,8 +286,8 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
enum box_lines lines = BOX_LINES_DEFAULT; enum box_lines lines = BOX_LINES_DEFAULT;
char *title, *cause = NULL; char *title, *cause = NULL;
int flags = 0, starting_choice = 0; int flags = 0, starting_choice = 0;
u_int px, py, i, count = args_count(args); u_int px, py, sx, sy, i, count = args_count(args);
struct options *o = target->s->curw->window->options; struct options *o = target->w->options;
struct options_entry *oe; struct options_entry *oe;
if (args_has(args, 'C')) { if (args_has(args, 'C')) {
@@ -335,9 +335,6 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
} }
if (menu->count == 0) if (menu->count == 0)
goto out; goto out;
if (!cmd_display_menu_get_menu_pos(tc, item, args, &px, &py,
menu->width + 4, menu->count + 2))
goto out;
value = args_get(args, 'b'); value = args_get(args, 'b');
if (value != NULL) { if (value != NULL) {
@@ -348,7 +345,11 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "menu-border-lines %s", cause); cmdq_error(item, "menu-border-lines %s", cause);
goto fail; goto fail;
} }
} } else
lines = options_get_number(o, "menu-border-lines");
menu_get_size(menu, lines, &sx, &sy);
if (!cmd_display_menu_get_menu_pos(tc, item, args, &px, &py, sx, sy))
goto out;
if (args_has(args, 'O')) if (args_has(args, 'O'))
flags |= MENU_STAYOPEN; flags |= MENU_STAYOPEN;

59
menu.c
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: menu.c,v 1.70 2026/08/17 07:33:55 nicm Exp $ */ /* $OpenBSD: menu.c,v 1.71 2026/09/21 12:14:32 nicm Exp $ */
/* /*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -51,6 +51,18 @@ struct menu_data {
void *data; void *data;
}; };
void
menu_get_size(struct menu *menu, enum box_lines lines, u_int *sx, u_int *sy)
{
if (lines == BOX_LINES_NONE) {
*sx = menu->item_width + 2;
*sy = menu->count;
} else {
*sx = menu->width + 4;
*sy = menu->count + 2;
}
}
void void
menu_add_items(struct menu *menu, const struct menu_item *items, menu_add_items(struct menu *menu, const struct menu_item *items,
struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs) struct cmdq_item *qitem, struct client *c, struct cmd_find_state *fs)
@@ -142,6 +154,8 @@ menu_add_item(struct menu *menu, const struct menu_item *item,
width = format_width(new_item->name); width = format_width(new_item->name);
if (*new_item->name == '-') if (*new_item->name == '-')
width--; width--;
if (width > menu->item_width)
menu->item_width = width;
if (width > menu->width) if (width > menu->width)
menu->width = width; menu->width = width;
} }
@@ -238,7 +252,7 @@ menu_update(struct menu_data *md)
screen_write_clearscreen(&ctx, 8); screen_write_clearscreen(&ctx, 8);
if (md->border_lines != BOX_LINES_NONE) { if (md->border_lines != BOX_LINES_NONE) {
screen_write_box(&ctx, menu->width + 4, menu->count + 2, screen_write_box(&ctx, menu_width(md), menu_height(md),
md->border_lines, &md->border_style_gc, menu->title); md->border_lines, &md->border_style_gc, menu->title);
} }
@@ -286,11 +300,13 @@ menu_destroy(struct window *w)
void void
menu_get_cursor(struct menu_data *md, u_int *cx, u_int *cy) menu_get_cursor(struct menu_data *md, u_int *cx, u_int *cy)
{ {
*cx = md->px + 2; u_int border = (md->border_lines != BOX_LINES_NONE);
*cx = md->px + 1 + border;
if (md->choice == -1) if (md->choice == -1)
*cy = md->py; *cy = md->py;
else else
*cy = md->py + 1 + md->choice; *cy = md->py + border + md->choice;
} }
struct screen * struct screen *
@@ -302,13 +318,19 @@ menu_screen(struct menu_data *md)
u_int u_int
menu_width(struct menu_data *md) menu_width(struct menu_data *md)
{ {
return (md->menu->width + 4); u_int sx, sy;
menu_get_size(md->menu, md->border_lines, &sx, &sy);
return (sx);
} }
u_int u_int
menu_height(struct menu_data *md) menu_height(struct menu_data *md)
{ {
return (md->menu->count + 2); u_int sx, sy;
menu_get_size(md->menu, md->border_lines, &sx, &sy);
return (sy);
} }
u_int u_int
@@ -338,6 +360,7 @@ menu_key(struct client *c, struct menu_data *md, struct key_event *event)
enum cmd_parse_status status; enum cmd_parse_status status;
char *error; char *error;
key_code key; key_code key;
u_int border;
if (KEYC_IS_MOUSE(event->key)) { if (KEYC_IS_MOUSE(event->key)) {
/* /*
@@ -353,10 +376,10 @@ menu_key(struct client *c, struct menu_data *md, struct key_event *event)
return (1); return (1);
return (0); return (0);
} }
if (m->x < md->px || border = (md->border_lines != BOX_LINES_NONE);
m->x > md->px + 4 + menu->width || if (m->x < md->px || m->x >= md->px + menu_width(md) ||
m->y < md->py + 1 || m->y < md->py + border ||
m->y > md->py + 1 + n - 1) { m->y >= md->py + border + n) {
if (~md->flags & MENU_STAYOPEN) { if (~md->flags & MENU_STAYOPEN) {
if (!move && MOUSE_RELEASE(m->b)) if (!move && MOUSE_RELEASE(m->b))
return (1); return (1);
@@ -379,7 +402,7 @@ menu_key(struct client *c, struct menu_data *md, struct key_event *event)
if (!MOUSE_WHEEL(m->b) && !MOUSE_DRAG(m->b)) if (!MOUSE_WHEEL(m->b) && !MOUSE_DRAG(m->b))
goto chosen; goto chosen;
} }
md->choice = m->y - (md->py + 1); md->choice = m->y - (md->py + border);
if (md->choice != old) if (md->choice != old)
server_redraw_window_menu(md->w); server_redraw_window_menu(md->w);
return (0); return (0);
@@ -546,20 +569,16 @@ menu_resize(struct menu_data *md, struct window *w)
if (md == NULL) if (md == NULL)
return; return;
nx = md->px; nx = md->px;
ny = md->py; ny = md->py;
sx = md->menu->width + 4; menu_get_size(md->menu, md->border_lines, &sx, &sy);
sy = md->menu->count + 2;
if (nx + sx > w->sx) { if (nx + sx > w->sx) {
if (w->sx <= sx) if (w->sx <= sx)
nx = 0; nx = 0;
else else
nx = w->sx - sx; nx = w->sx - sx;
} }
if (ny + sy > w->sy) { if (ny + sy > w->sy) {
if (w->sy <= sy) if (w->sy <= sy)
ny = 0; ny = 0;
@@ -591,8 +610,9 @@ menu_display(struct menu *menu, int flags, int starting_choice,
w = fs->w; w = fs->w;
o = w->options; o = w->options;
sx = menu->width + 4; if (lines == BOX_LINES_DEFAULT)
sy = menu->count + 2; lines = options_get_number(o, "menu-border-lines");
menu_get_size(menu, lines, &sx, &sy);
if (sx >= w->sx) if (sx >= w->sx)
px = 0; px = 0;
else if (px + sx > w->sx) else if (px + sx > w->sx)
@@ -604,9 +624,6 @@ menu_display(struct menu *menu, int flags, int starting_choice,
w->menu_last_px = px; w->menu_last_px = px;
w->menu_last_py = py; w->menu_last_py = py;
if (lines == BOX_LINES_DEFAULT)
lines = options_get_number(o, "menu-border-lines");
md = xcalloc(1, sizeof *md); md = xcalloc(1, sizeof *md);
md->w = w; md->w = w;
md->flags = flags; md->flags = flags;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: mode-tree.c,v 1.101 2026/08/05 07:50:21 nicm Exp $ */ /* $OpenBSD: mode-tree.c,v 1.102 2026/09/21 12:14:32 nicm Exp $ */
/* /*
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1375,12 +1375,14 @@ static void
mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x, mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
u_int y, int outside) u_int y, int outside)
{ {
struct window *w = mtd->wp->window;
struct mode_tree_item *mti; struct mode_tree_item *mti;
struct menu *menu; struct menu *menu;
const struct menu_item *items; const struct menu_item *items;
struct mode_tree_menu *mtm; struct mode_tree_menu *mtm;
char *title; char *title;
u_int line; enum box_lines lines;
u_int line, sx, sy;
if (mtd->offset + y > mtd->line_size - 1) if (mtd->offset + y > mtd->line_size - 1)
line = mtd->current; line = mtd->current;
@@ -1405,14 +1407,17 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
mtm->line = line; mtm->line = line;
mtd->references++; mtd->references++;
if (x >= (menu->width + 4) / 2) lines = options_get_number(w->options, "menu-border-lines");
x -= (menu->width + 4) / 2; menu_get_size(menu, lines, &sx, &sy);
if (x >= sx / 2)
x -= sx / 2;
else else
x = 0; x = 0;
x += mtd->wp->xoff; x += mtd->wp->xoff;
y += mtd->wp->yoff; y += mtd->wp->yoff;
if (menu_display(menu, 0, 0, NULL, x, y, c, BOX_LINES_DEFAULT, NULL,
NULL, NULL, NULL, mode_tree_menu_callback, mtm) != 0) { if (menu_display(menu, 0, 0, NULL, x, y, c, lines, NULL, NULL, NULL,
NULL, mode_tree_menu_callback, mtm) != 0) {
mode_tree_remove_ref(mtd); mode_tree_remove_ref(mtd);
free(mtm); free(mtm);
menu_free(menu); menu_free(menu);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: screen-write.c,v 1.291 2026/09/21 10:22:31 nicm Exp $ */ /* $OpenBSD: screen-write.c,v 1.292 2026/09/21 12:14:32 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -833,34 +833,39 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, int choice,
struct screen *s = ctx->s; struct screen *s = ctx->s;
struct grid_cell default_gc; struct grid_cell default_gc;
const struct grid_cell *gc = &default_gc; const struct grid_cell *gc = &default_gc;
u_int cx, cy, i, j, width = menu->width; u_int border, cx = s->cx, cy = s->cy, i, j, width;
const char *name; const char *name;
cx = s->cx;
cy = s->cy;
memcpy(&default_gc, menu_gc, sizeof default_gc); memcpy(&default_gc, menu_gc, sizeof default_gc);
screen_write_box(ctx, menu->width + 4, menu->count + 2, lines, if (lines == BOX_LINES_NONE) {
border_gc, menu->title); border = 0;
width = menu->item_width;
} else {
border = 1;
width = menu->width;
screen_write_box(ctx, width + 4, menu->count + 2, lines,
border_gc, menu->title);
}
for (i = 0; i < menu->count; i++) { for (i = 0; i < menu->count; i++) {
name = menu->items[i].name; name = menu->items[i].name;
if (name == NULL) { if (name == NULL) {
screen_write_cursormove(ctx, cx, cy + 1 + i, 0); screen_write_cursormove(ctx, cx, cy + border + i, 0);
screen_write_hline(ctx, width + 4, 1, 1, lines, screen_write_hline(ctx, width + 2 + (2 * border), 1, 1,
border_gc); lines, border_gc);
continue; continue;
} }
if (choice >= 0 && i == (u_int)choice && *name != '-') if (choice >= 0 && i == (u_int)choice && *name != '-')
gc = choice_gc; gc = choice_gc;
screen_write_cursormove(ctx, cx + 1, cy + 1 + i, 0); screen_write_cursormove(ctx, cx + border, cy + border + i, 0);
for (j = 0; j < width + 2; j++) for (j = 0; j < width + 2; j++)
screen_write_putc(ctx, gc, ' '); screen_write_putc(ctx, gc, ' ');
screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0); screen_write_cursormove(ctx, cx + border + 1, cy + border + i,
0);
if (*name == '-') { if (*name == '-') {
default_gc.attr |= GRID_ATTR_DIM; default_gc.attr |= GRID_ATTR_DIM;
format_draw(ctx, gc, width, name + 1, NULL, 0); format_draw(ctx, gc, width, name + 1, NULL, 0);

4
tmux.h
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1443 2026/09/21 10:33:16 nicm Exp $ */ /* $OpenBSD: tmux.h,v 1.1444 2026/09/21 12:14:32 nicm Exp $ */
/* /*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -1148,6 +1148,7 @@ struct menu {
struct menu_item *items; struct menu_item *items;
u_int count; u_int count;
u_int width; u_int width;
u_int item_width;
}; };
typedef void (*menu_choice_cb)(struct menu *, u_int, key_code, void *); typedef void (*menu_choice_cb)(struct menu *, u_int, key_code, void *);
@@ -4093,6 +4094,7 @@ void menu_add_item(struct menu *, const struct menu_item *,
struct cmdq_item *, struct client *, struct cmdq_item *, struct client *,
struct cmd_find_state *); struct cmd_find_state *);
void menu_free(struct menu *); void menu_free(struct menu *);
void menu_get_size(struct menu *, enum box_lines, u_int *, u_int *);
int menu_display(struct menu *, int, int, struct cmdq_item *, int menu_display(struct menu *, int, int, struct cmdq_item *,
u_int, u_int, struct client *, enum box_lines, const char *, u_int, u_int, struct client *, enum box_lines, const char *,
const char *, const char *, struct cmd_find_state *, const char *, const char *, struct cmd_find_state *,