From dda0e4d489acb9ff6978b2a841726361f853bbc4 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 21 Sep 2026 12:14:32 +0000 Subject: [PATCH] Add support for borderless menus, like panes. GitHub issue 5447 from harikp2002 at gmail dot com. --- cmd-display-menu.c | 15 ++++++------ menu.c | 59 +++++++++++++++++++++++++++++----------------- mode-tree.c | 17 ++++++++----- screen-write.c | 29 +++++++++++++---------- tmux.h | 4 +++- 5 files changed, 77 insertions(+), 47 deletions(-) diff --git a/cmd-display-menu.c b/cmd-display-menu.c index de5c6ead5..a73537584 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -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 @@ -286,8 +286,8 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) enum box_lines lines = BOX_LINES_DEFAULT; char *title, *cause = NULL; int flags = 0, starting_choice = 0; - u_int px, py, i, count = args_count(args); - struct options *o = target->s->curw->window->options; + u_int px, py, sx, sy, i, count = args_count(args); + struct options *o = target->w->options; struct options_entry *oe; if (args_has(args, 'C')) { @@ -335,9 +335,6 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) } if (menu->count == 0) 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'); 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); 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')) flags |= MENU_STAYOPEN; diff --git a/menu.c b/menu.c index 2816056a4..cb087296e 100644 --- a/menu.c +++ b/menu.c @@ -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 @@ -51,6 +51,18 @@ struct menu_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 menu_add_items(struct menu *menu, const struct menu_item *items, 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); if (*new_item->name == '-') width--; + if (width > menu->item_width) + menu->item_width = width; if (width > menu->width) menu->width = width; } @@ -238,7 +252,7 @@ menu_update(struct menu_data *md) screen_write_clearscreen(&ctx, 8); 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); } @@ -286,11 +300,13 @@ menu_destroy(struct window *w) void 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) *cy = md->py; else - *cy = md->py + 1 + md->choice; + *cy = md->py + border + md->choice; } struct screen * @@ -302,13 +318,19 @@ menu_screen(struct menu_data *md) u_int 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 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 @@ -338,6 +360,7 @@ menu_key(struct client *c, struct menu_data *md, struct key_event *event) enum cmd_parse_status status; char *error; key_code key; + u_int border; 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 (0); } - if (m->x < md->px || - m->x > md->px + 4 + menu->width || - m->y < md->py + 1 || - m->y > md->py + 1 + n - 1) { + border = (md->border_lines != BOX_LINES_NONE); + if (m->x < md->px || m->x >= md->px + menu_width(md) || + m->y < md->py + border || + m->y >= md->py + border + n) { if (~md->flags & MENU_STAYOPEN) { if (!move && MOUSE_RELEASE(m->b)) 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)) goto chosen; } - md->choice = m->y - (md->py + 1); + md->choice = m->y - (md->py + border); if (md->choice != old) server_redraw_window_menu(md->w); return (0); @@ -546,20 +569,16 @@ menu_resize(struct menu_data *md, struct window *w) if (md == NULL) return; - nx = md->px; ny = md->py; - sx = md->menu->width + 4; - sy = md->menu->count + 2; - + menu_get_size(md->menu, md->border_lines, &sx, &sy); if (nx + sx > w->sx) { if (w->sx <= sx) nx = 0; else nx = w->sx - sx; } - if (ny + sy > w->sy) { if (w->sy <= sy) ny = 0; @@ -591,8 +610,9 @@ menu_display(struct menu *menu, int flags, int starting_choice, w = fs->w; o = w->options; - sx = menu->width + 4; - sy = menu->count + 2; + if (lines == BOX_LINES_DEFAULT) + lines = options_get_number(o, "menu-border-lines"); + menu_get_size(menu, lines, &sx, &sy); if (sx >= w->sx) px = 0; 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_py = py; - if (lines == BOX_LINES_DEFAULT) - lines = options_get_number(o, "menu-border-lines"); - md = xcalloc(1, sizeof *md); md->w = w; md->flags = flags; diff --git a/mode-tree.c b/mode-tree.c index 5132eb94c..bc31a5ba4 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -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 @@ -1375,12 +1375,14 @@ static void mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x, u_int y, int outside) { + struct window *w = mtd->wp->window; struct mode_tree_item *mti; struct menu *menu; const struct menu_item *items; struct mode_tree_menu *mtm; char *title; - u_int line; + enum box_lines lines; + u_int line, sx, sy; if (mtd->offset + y > mtd->line_size - 1) 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; mtd->references++; - if (x >= (menu->width + 4) / 2) - x -= (menu->width + 4) / 2; + lines = options_get_number(w->options, "menu-border-lines"); + menu_get_size(menu, lines, &sx, &sy); + if (x >= sx / 2) + x -= sx / 2; else x = 0; x += mtd->wp->xoff; 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); free(mtm); menu_free(menu); diff --git a/screen-write.c b/screen-write.c index e3772c438..1b3848247 100644 --- a/screen-write.c +++ b/screen-write.c @@ -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 @@ -833,34 +833,39 @@ screen_write_menu(struct screen_write_ctx *ctx, struct menu *menu, int choice, struct screen *s = ctx->s; struct grid_cell 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; - cx = s->cx; - cy = s->cy; - memcpy(&default_gc, menu_gc, sizeof default_gc); - screen_write_box(ctx, menu->width + 4, menu->count + 2, lines, - border_gc, menu->title); + if (lines == BOX_LINES_NONE) { + 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++) { name = menu->items[i].name; if (name == NULL) { - screen_write_cursormove(ctx, cx, cy + 1 + i, 0); - screen_write_hline(ctx, width + 4, 1, 1, lines, - border_gc); + screen_write_cursormove(ctx, cx, cy + border + i, 0); + screen_write_hline(ctx, width + 2 + (2 * border), 1, 1, + lines, border_gc); continue; } if (choice >= 0 && i == (u_int)choice && *name != '-') 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++) 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 == '-') { default_gc.attr |= GRID_ATTR_DIM; format_draw(ctx, gc, width, name + 1, NULL, 0); diff --git a/tmux.h b/tmux.h index eb25fb80d..c292ade9d 100644 --- a/tmux.h +++ b/tmux.h @@ -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 @@ -1148,6 +1148,7 @@ struct menu { struct menu_item *items; u_int count; u_int width; + u_int item_width; }; 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 cmd_find_state *); 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 *, u_int, u_int, struct client *, enum box_lines, const char *, const char *, const char *, struct cmd_find_state *,