Merge remote-tracking branch 'refs/remotes/tmux-openbsd/master'

* refs/remotes/tmux-openbsd/master:
  Add support for borderless menus, like panes. GitHub issue 5447 from harikp2002 at gmail dot com.
  Do not trim all lines to make a zero line grid which reflow does not like, from Kaixuan Li.
  Do not unzoom when resizing a floating pane that was created with -A. Similarly, skip hidden floating panes when changing Z order. Reported by Clark Wang.
This commit is contained in:
tmux update bot
2026-09-21 13:44:41 +00:00
9 changed files with 110 additions and 57 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>
@@ -285,8 +285,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')) {
@@ -334,9 +334,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) {
@@ -347,7 +344,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;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: cmd-join-pane.c,v 1.74 2026/08/03 20:29:52 nicm Exp $ */
/* $OpenBSD: cmd-join-pane.c,v 1.75 2026/09/21 10:33:16 nicm Exp $ */
/*
* Copyright (c) 2011 George Nachman <tmux@georgester.com>
@@ -133,7 +133,7 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
} else if (strcmp(position, "back") == 0) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_FOREACH(owp, &w->z_index, zentry) {
if (!window_pane_is_floating(owp))
if (!window_pane_is_floating_with_hidden(owp))
break;
}
if (owp != NULL)
@@ -142,24 +142,30 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
} else if (strcmp(position, "forward") == 0) {
owp = TAILQ_PREV(wp, window_panes_zindex, zentry);
while (owp != NULL && owp->layout_cell == NULL)
owp = TAILQ_PREV(owp, window_panes_zindex, zentry);
if (owp != NULL) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_BEFORE(owp, wp, zentry);
}
} else if (strcmp(position, "backward") == 0) {
owp = TAILQ_NEXT(wp, zentry);
while (owp != NULL && owp->layout_cell == NULL)
owp = TAILQ_NEXT(owp, zentry);
if (owp != NULL && window_pane_is_floating(owp)) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_AFTER(&w->z_index, owp, wp, zentry);
}
} else if (strcmp(position, "forward-loop") == 0) {
owp = TAILQ_PREV(wp, window_panes_zindex, zentry);
while (owp != NULL && owp->layout_cell == NULL)
owp = TAILQ_PREV(owp, window_panes_zindex, zentry);
TAILQ_REMOVE(&w->z_index, wp, zentry);
if (owp != NULL)
TAILQ_INSERT_BEFORE(owp, wp, zentry);
else {
TAILQ_FOREACH(owp, &w->z_index, zentry) {
if (!window_pane_is_floating(owp))
if (!window_pane_is_floating_with_hidden(owp))
break;
}
if (owp != NULL)
@@ -169,6 +175,8 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
}
} else if (strcmp(position, "backward-loop") == 0) {
owp = TAILQ_NEXT(wp, zentry);
while (owp != NULL && owp->layout_cell == NULL)
owp = TAILQ_NEXT(owp, zentry);
if (owp != NULL && window_pane_is_floating(owp)) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_AFTER(&w->z_index, owp, wp, zentry);
@@ -347,8 +355,10 @@ cmd_join_pane_zindex(struct cmdq_item *item, struct winlink *wl,
n = 0;
TAILQ_FOREACH(owp, &w->z_index, zentry) {
if (!window_pane_is_floating(owp))
if (!window_pane_is_floating_with_hidden(owp))
break;
if (owp->layout_cell == NULL)
continue;
if (n >= z)
break;
n++;
@@ -443,7 +453,6 @@ cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "pane is not floating");
return (CMD_RETURN_ERROR);
}
server_unzoom_window(dst_w);
if ((s = args_get(args, 'P')) != NULL)
return (cmd_join_pane_place(item, dst_wl, dst_wp, s));
if ((s = args_get(args, 'z')) != NULL)

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: cmd-resize-pane.c,v 1.68 2026/08/31 07:44:39 nicm Exp $ */
/* $OpenBSD: cmd-resize-pane.c,v 1.69 2026/09/21 10:33:16 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -91,7 +91,8 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
server_redraw_window(w);
return (CMD_RETURN_NORMAL);
}
server_unzoom_window(w);
if (!window_pane_is_floating(wp))
server_unzoom_window(w);
lc = wp->layout_cell; /* may have been replaced by unzoom */
if (args_has(args, 'x')) {

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>
@@ -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;

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>
@@ -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);

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>
@@ -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);

5
tmux.h
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1442 2026/09/21 10:22:31 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>
@@ -1182,6 +1182,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 *);
@@ -3804,6 +3805,7 @@ int window_pane_get_pane_status(struct window_pane *);
struct style_range *window_pane_status_get_range(struct window_pane *, u_int,
u_int);
int window_pane_is_floating(struct window_pane *);
int window_pane_is_floating_with_hidden(struct window_pane *);
/* window-border.c */
void window_set_fill_cells(struct window *);
@@ -4143,6 +4145,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 *,

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: window-copy.c,v 1.430 2026/09/21 10:22:31 nicm Exp $ */
/* $OpenBSD: window-copy.c,v 1.431 2026/09/21 10:43:37 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -401,7 +401,7 @@ window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx,
sy = screen_hsize(src) + screen_size_y(src);
if (trim) {
while (sy > screen_hsize(src)) {
while (sy > screen_hsize(src) + 1) {
gl = grid_peek_line(src->grid, sy - 1);
if (gl == NULL || gl->cellused != 0)
break;

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: window.c,v 1.376 2026/09/21 10:22:31 nicm Exp $ */
/* $OpenBSD: window.c,v 1.377 2026/09/21 10:33:16 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2913,3 +2913,15 @@ window_pane_is_floating(struct window_pane *wp)
return (0);
return (1);
}
int
window_pane_is_floating_with_hidden(struct window_pane *wp)
{
struct layout_cell *lc = wp->layout_cell;
if (lc == NULL)
lc = wp->saved_layout_cell;
if (lc == NULL || (lc->flags & LAYOUT_CELL_FLOATING) == 0)
return (0);
return (1);
}