mirror of
https://github.com/tmux/tmux.git
synced 2026-09-23 13:23:57 +00:00
Compare commits
18 Commits
margins-te
...
no_more_ov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bf001b3c6 | ||
|
|
aa3f6a49d7 | ||
|
|
b98ce20a10 | ||
|
|
5ea118e3e0 | ||
|
|
b15c62ac07 | ||
|
|
7049aa826a | ||
|
|
19320c6969 | ||
|
|
78c0dc5be0 | ||
|
|
81fa44f263 | ||
|
|
ba1bfeeb9c | ||
|
|
5047e4eb1a | ||
|
|
8a1f4620b0 | ||
|
|
7d32e7f379 | ||
|
|
6671efcaf7 | ||
|
|
858a9d7376 | ||
|
|
980877fb5c | ||
|
|
c7a6a735bc | ||
|
|
381eaaa3a3 |
12
.github/workflows/regress.yml
vendored
12
.github/workflows/regress.yml
vendored
@@ -27,10 +27,10 @@ jobs:
|
||||
runner: ubuntu-24.04
|
||||
make: make
|
||||
configure: --enable-utf8proc --enable-asan
|
||||
- name: ubuntu-24.04-arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
make: make
|
||||
configure: --enable-utf8proc --enable-asan
|
||||
#- name: ubuntu-24.04-arm64
|
||||
# runner: ubuntu-24.04-arm
|
||||
# make: make
|
||||
# configure: --enable-utf8proc --enable-asan
|
||||
- name: macos-26-arm64
|
||||
runner: macos-26
|
||||
make: gmake
|
||||
@@ -72,14 +72,14 @@ jobs:
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
sh autogen.sh
|
||||
sh autogen.sh
|
||||
./configure ${{ matrix.configure }}
|
||||
${{ matrix.make }} -j"$(getconf _NPROCESSORS_ONLN)"
|
||||
|
||||
- name: test
|
||||
run: |
|
||||
cd regress
|
||||
${{ matrix.make }} -j"$(getconf _NPROCESSORS_ONLN)"
|
||||
${{ matrix.make }}
|
||||
|
||||
- name: logs
|
||||
if: failure()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-display-menu.c,v 1.55 2026/09/21 12:14:32 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-display-menu.c,v 1.54 2026/09/21 10:22:31 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, sx, sy, i, count = args_count(args);
|
||||
struct options *o = target->w->options;
|
||||
u_int px, py, i, count = args_count(args);
|
||||
struct options *o = target->s->curw->window->options;
|
||||
struct options_entry *oe;
|
||||
|
||||
if (args_has(args, 'C')) {
|
||||
@@ -334,6 +334,9 @@ 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) {
|
||||
@@ -344,11 +347,7 @@ 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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-join-pane.c,v 1.75 2026/09/21 10:33:16 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-join-pane.c,v 1.74 2026/08/03 20:29:52 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_with_hidden(owp))
|
||||
if (!window_pane_is_floating(owp))
|
||||
break;
|
||||
}
|
||||
if (owp != NULL)
|
||||
@@ -142,30 +142,24 @@ 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_with_hidden(owp))
|
||||
if (!window_pane_is_floating(owp))
|
||||
break;
|
||||
}
|
||||
if (owp != NULL)
|
||||
@@ -175,8 +169,6 @@ 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);
|
||||
@@ -355,10 +347,8 @@ 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_with_hidden(owp))
|
||||
if (!window_pane_is_floating(owp))
|
||||
break;
|
||||
if (owp->layout_cell == NULL)
|
||||
continue;
|
||||
if (n >= z)
|
||||
break;
|
||||
n++;
|
||||
@@ -453,6 +443,7 @@ 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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-queue.c,v 1.124 2026/09/22 06:46:50 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-queue.c,v 1.123 2026/08/24 20:34:26 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -580,9 +580,6 @@ cmdq_fire_command(struct cmdq_item *item)
|
||||
int flags, quiet = 0;
|
||||
char *tmp;
|
||||
|
||||
if (item->client != NULL && (item->client->flags & CLIENT_DEAD))
|
||||
return (CMD_RETURN_ERROR);
|
||||
|
||||
if (cfg_finished)
|
||||
cmdq_add_message(item);
|
||||
if (log_get_level() > 1) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-resize-pane.c,v 1.69 2026/09/21 10:33:16 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-resize-pane.c,v 1.68 2026/08/31 07:44:39 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -91,8 +91,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
|
||||
server_redraw_window(w);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
if (!window_pane_is_floating(wp))
|
||||
server_unzoom_window(w);
|
||||
server_unzoom_window(w);
|
||||
lc = wp->layout_cell; /* may have been replaced by unzoom */
|
||||
|
||||
if (args_has(args, 'x')) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: cmd-wait-for.c,v 1.24 2026/09/22 06:46:50 nicm Exp $ */
|
||||
/* $OpenBSD: cmd-wait-for.c,v 1.23 2026/07/10 13:38:45 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -480,40 +480,6 @@ cmd_wait_for_unlock(struct cmdq_item *item, const char *name,
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_wait_for_client_lost(struct client *c)
|
||||
{
|
||||
struct wait_channel *wc, *wc1;
|
||||
struct wait_item *wi, *wi1;
|
||||
struct wait_event_item *wei, *wei1;
|
||||
|
||||
TAILQ_FOREACH_SAFE(wei, &wait_event_items, entry, wei1) {
|
||||
if (cmdq_get_client(wei->item) == c) {
|
||||
TAILQ_REMOVE(&wait_event_items, wei, entry);
|
||||
cmdq_continue(wei->item);
|
||||
cmd_wait_for_event_free(wei);
|
||||
}
|
||||
}
|
||||
|
||||
RB_FOREACH_SAFE(wc, wait_channels, &wait_channels, wc1) {
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->waiters, entry, wi1) {
|
||||
if (cmdq_get_client(wi->item) == c) {
|
||||
cmdq_continue(wi->item);
|
||||
TAILQ_REMOVE(&wc->waiters, wi, entry);
|
||||
free(wi);
|
||||
}
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(wi, &wc->lockers, entry, wi1) {
|
||||
if (cmdq_get_client(wi->item) == c) {
|
||||
cmdq_continue(wi->item);
|
||||
TAILQ_REMOVE(&wc->lockers, wi, entry);
|
||||
free(wi);
|
||||
}
|
||||
}
|
||||
cmd_wait_for_remove_empty(wc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cmd_wait_for_flush(void)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: key-bindings.c,v 1.193 2026/09/21 20:45:48 nicm Exp $ */
|
||||
/* $OpenBSD: key-bindings.c,v 1.192 2026/08/06 09:05:04 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -523,7 +523,7 @@ key_bindings_init(void)
|
||||
"bind -n TripleClick1Pane { select-pane -t=; if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -H; send -X select-line; run -d0.3; send -X copy-pipe-and-cancel } }",
|
||||
|
||||
/* Mouse button 1 on border. */
|
||||
"bind -n MouseDown1Border { select-pane -t= }",
|
||||
"bind -n MouseDown1Border { select-pane -M }",
|
||||
|
||||
/* Mouse button 1 drag on border. */
|
||||
"bind -n MouseDrag1Border { resize-pane -M }",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: layout-custom.c,v 1.43 2026/09/22 06:48:01 nicm Exp $ */
|
||||
/* $OpenBSD: layout-custom.c,v 1.42 2026/09/20 08:37:47 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -307,37 +307,6 @@ bad:
|
||||
return (xstrdup("0000,"));
|
||||
}
|
||||
|
||||
/* Get a floating pane cell's z-index in the layout being dumped. */
|
||||
static u_int
|
||||
layout_cell_zindex(struct layout_cell *lc)
|
||||
{
|
||||
struct window_pane *wp = lc->wp, *wq;
|
||||
struct window *w = wp->window;
|
||||
struct layout_cell *other;
|
||||
int saved = (lc == wp->saved_layout_cell);
|
||||
u_int i = 0;
|
||||
|
||||
if (saved &&
|
||||
w->active != NULL &&
|
||||
(w->active->flags & PANE_ZOOMED) &&
|
||||
(w->active->saved_layout_cell->flags & LAYOUT_CELL_FLOATING)) {
|
||||
if (wp == w->active)
|
||||
return (0);
|
||||
i++;
|
||||
}
|
||||
TAILQ_FOREACH(wq, &w->z_index, zentry) {
|
||||
if (wq == wp)
|
||||
break;
|
||||
if (saved)
|
||||
other = wq->saved_layout_cell;
|
||||
else
|
||||
other = wq->layout_cell;
|
||||
if (other != NULL && (other->flags & LAYOUT_CELL_FLOATING))
|
||||
i++;
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* Append information for a single cell in a JSON (v2) format. */
|
||||
static int
|
||||
layout_append_v2(struct layout_cell *lc, struct layout_string *ls)
|
||||
@@ -346,7 +315,7 @@ layout_append_v2(struct layout_cell *lc, struct layout_string *ls)
|
||||
struct window_pane *wp;
|
||||
enum layout_type type;
|
||||
char c;
|
||||
u_int i, n, z;
|
||||
u_int i, n;
|
||||
|
||||
if (lc == NULL)
|
||||
return (-1);
|
||||
@@ -387,10 +356,9 @@ layout_append_v2(struct layout_cell *lc, struct layout_string *ls)
|
||||
if (window_pane_index(wp, &i) != 0)
|
||||
return (-1);
|
||||
layout_string_write(ls, ",\"i\":%u", i);
|
||||
if (lc->flags & LAYOUT_CELL_FLOATING) {
|
||||
z = layout_cell_zindex(lc);
|
||||
layout_string_write(ls, ",\"z\":%u", z);
|
||||
}
|
||||
if ((lc->flags & LAYOUT_CELL_FLOATING) &&
|
||||
window_pane_zindex(wp, &i) == 0)
|
||||
layout_string_write(ls, ",\"z\":%u", i);
|
||||
layout_string_write(ls, ",\"I\":\"%%%u\"", wp->id);
|
||||
}
|
||||
|
||||
|
||||
59
menu.c
59
menu.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: menu.c,v 1.71 2026/09/21 12:14:32 nicm Exp $ */
|
||||
/* $OpenBSD: menu.c,v 1.70 2026/08/17 07:33:55 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -51,18 +51,6 @@ 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)
|
||||
@@ -154,8 +142,6 @@ 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;
|
||||
}
|
||||
@@ -252,7 +238,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(md), menu_height(md),
|
||||
screen_write_box(&ctx, menu->width + 4, menu->count + 2,
|
||||
md->border_lines, &md->border_style_gc, menu->title);
|
||||
}
|
||||
|
||||
@@ -300,13 +286,11 @@ menu_destroy(struct window *w)
|
||||
void
|
||||
menu_get_cursor(struct menu_data *md, u_int *cx, u_int *cy)
|
||||
{
|
||||
u_int border = (md->border_lines != BOX_LINES_NONE);
|
||||
|
||||
*cx = md->px + 1 + border;
|
||||
*cx = md->px + 2;
|
||||
if (md->choice == -1)
|
||||
*cy = md->py;
|
||||
else
|
||||
*cy = md->py + border + md->choice;
|
||||
*cy = md->py + 1 + md->choice;
|
||||
}
|
||||
|
||||
struct screen *
|
||||
@@ -318,19 +302,13 @@ menu_screen(struct menu_data *md)
|
||||
u_int
|
||||
menu_width(struct menu_data *md)
|
||||
{
|
||||
u_int sx, sy;
|
||||
|
||||
menu_get_size(md->menu, md->border_lines, &sx, &sy);
|
||||
return (sx);
|
||||
return (md->menu->width + 4);
|
||||
}
|
||||
|
||||
u_int
|
||||
menu_height(struct menu_data *md)
|
||||
{
|
||||
u_int sx, sy;
|
||||
|
||||
menu_get_size(md->menu, md->border_lines, &sx, &sy);
|
||||
return (sy);
|
||||
return (md->menu->count + 2);
|
||||
}
|
||||
|
||||
u_int
|
||||
@@ -360,7 +338,6 @@ 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)) {
|
||||
/*
|
||||
@@ -376,10 +353,10 @@ menu_key(struct client *c, struct menu_data *md, struct key_event *event)
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
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 (m->x < md->px ||
|
||||
m->x > md->px + 4 + menu->width ||
|
||||
m->y < md->py + 1 ||
|
||||
m->y > md->py + 1 + n - 1) {
|
||||
if (~md->flags & MENU_STAYOPEN) {
|
||||
if (!move && MOUSE_RELEASE(m->b))
|
||||
return (1);
|
||||
@@ -402,7 +379,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 + border);
|
||||
md->choice = m->y - (md->py + 1);
|
||||
if (md->choice != old)
|
||||
server_redraw_window_menu(md->w);
|
||||
return (0);
|
||||
@@ -569,16 +546,20 @@ menu_resize(struct menu_data *md, struct window *w)
|
||||
|
||||
if (md == NULL)
|
||||
return;
|
||||
|
||||
nx = md->px;
|
||||
ny = md->py;
|
||||
|
||||
menu_get_size(md->menu, md->border_lines, &sx, &sy);
|
||||
sx = md->menu->width + 4;
|
||||
sy = md->menu->count + 2;
|
||||
|
||||
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;
|
||||
@@ -610,9 +591,8 @@ menu_display(struct menu *menu, int flags, int starting_choice,
|
||||
w = fs->w;
|
||||
o = w->options;
|
||||
|
||||
if (lines == BOX_LINES_DEFAULT)
|
||||
lines = options_get_number(o, "menu-border-lines");
|
||||
menu_get_size(menu, lines, &sx, &sy);
|
||||
sx = menu->width + 4;
|
||||
sy = menu->count + 2;
|
||||
if (sx >= w->sx)
|
||||
px = 0;
|
||||
else if (px + sx > w->sx)
|
||||
@@ -624,6 +604,9 @@ 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;
|
||||
|
||||
17
mode-tree.c
17
mode-tree.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: mode-tree.c,v 1.102 2026/09/21 12:14:32 nicm Exp $ */
|
||||
/* $OpenBSD: mode-tree.c,v 1.101 2026/08/05 07:50:21 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -1375,14 +1375,12 @@ 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;
|
||||
enum box_lines lines;
|
||||
u_int line, sx, sy;
|
||||
u_int line;
|
||||
|
||||
if (mtd->offset + y > mtd->line_size - 1)
|
||||
line = mtd->current;
|
||||
@@ -1407,17 +1405,14 @@ mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x,
|
||||
mtm->line = line;
|
||||
mtd->references++;
|
||||
|
||||
lines = options_get_number(w->options, "menu-border-lines");
|
||||
menu_get_size(menu, lines, &sx, &sy);
|
||||
if (x >= sx / 2)
|
||||
x -= sx / 2;
|
||||
if (x >= (menu->width + 4) / 2)
|
||||
x -= (menu->width + 4) / 2;
|
||||
else
|
||||
x = 0;
|
||||
x += mtd->wp->xoff;
|
||||
y += mtd->wp->yoff;
|
||||
|
||||
if (menu_display(menu, 0, 0, NULL, x, y, c, lines, NULL, NULL, NULL,
|
||||
NULL, mode_tree_menu_callback, mtm) != 0) {
|
||||
if (menu_display(menu, 0, 0, NULL, x, y, c, BOX_LINES_DEFAULT, NULL,
|
||||
NULL, NULL, NULL, mode_tree_menu_callback, mtm) != 0) {
|
||||
mode_tree_remove_ref(mtd);
|
||||
free(mtm);
|
||||
menu_free(menu);
|
||||
|
||||
@@ -1,17 +1,33 @@
|
||||
TESTS!= echo *.sh
|
||||
LOGDIR=logs
|
||||
|
||||
.PHONY: all prepare $(TESTS)
|
||||
.PHONY: all
|
||||
.NOTPARALLEL: all
|
||||
|
||||
all: prepare $(TESTS)
|
||||
@failed=0; failures=; \
|
||||
all:
|
||||
@mkdir -p "$(LOGDIR)"; \
|
||||
rm -f "$(LOGDIR)"/*.log; \
|
||||
failed=0; failures=; \
|
||||
for test in $(TESTS); do \
|
||||
base=$${test##*/}; \
|
||||
log="$(LOGDIR)/$${base%.sh}.log"; \
|
||||
if [ -f "$$log" ]; then \
|
||||
rm -f "$$log"; \
|
||||
printf '%-40s ' "$$test"; \
|
||||
start=$$(date +%s); \
|
||||
env -i LC_CTYPE=C.UTF-8 MallocNanoZone=0 \
|
||||
sh -x "$$test" >"$$log" 2>&1; \
|
||||
if [ $$? -eq 0 ]; then \
|
||||
end=$$(date +%s); \
|
||||
rm -f "$$log"; \
|
||||
echo "PASS ($$((end - start))s)"; \
|
||||
else \
|
||||
end=$$(date +%s); \
|
||||
echo "FAIL ($$((end - start))s)"; \
|
||||
echo " log: $$log"; \
|
||||
failed=1; \
|
||||
failures="$$failures $$test"; \
|
||||
fi; \
|
||||
sleep 1; \
|
||||
done; \
|
||||
if [ "$$failed" -ne 0 ]; then \
|
||||
echo; \
|
||||
@@ -23,22 +39,3 @@ all: prepare $(TESTS)
|
||||
rmdir "$(LOGDIR)" 2>/dev/null || true; \
|
||||
fi; \
|
||||
exit $$failed
|
||||
|
||||
prepare:
|
||||
@mkdir -p "$(LOGDIR)"
|
||||
@rm -f "$(LOGDIR)"/*.log
|
||||
|
||||
$(TESTS): prepare
|
||||
@base="$@"; base=$${base##*/}; \
|
||||
log="$(LOGDIR)/$${base%.sh}.log"; \
|
||||
start=$$(date +%s); \
|
||||
if env -i LC_CTYPE=C.UTF-8 MallocNanoZone=0 \
|
||||
sh -x "$@" >"$$log" 2>&1; then \
|
||||
end=$$(date +%s); \
|
||||
rm -f "$$log"; \
|
||||
printf '%-40s PASS (%ss)\n' "$@" "$$((end - start))"; \
|
||||
else \
|
||||
end=$$(date +%s); \
|
||||
printf '%-40s FAIL (%ss)\n log: %s\n' \
|
||||
"$@" "$$((end - start))" "$$log"; \
|
||||
fi
|
||||
|
||||
@@ -17,7 +17,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest$$"
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
DIR=$(mktemp -d)
|
||||
|
||||
@@ -19,7 +19,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest$$"
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
DIR=$(mktemp -d)
|
||||
|
||||
@@ -10,7 +10,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest$$"
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
OUT=$(mktemp)
|
||||
|
||||
@@ -10,7 +10,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest$$"
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
FIFO=$(mktemp -u)
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Trimming a blank source must leave a visible line for cursor reflow.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
export PATH TERM
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX kill-server 2>/dev/null
|
||||
}
|
||||
trap cleanup 0
|
||||
trap 'exit 1' 1 2 3 15
|
||||
|
||||
$TMUX new-session -d -x80 -y24 -s test 'sleep 100' || exit 1
|
||||
$TMUX set-option -g window-size manual || exit 1
|
||||
$TMUX new-window -t test:1 'sleep 100' || exit 1
|
||||
$TMUX resize-window -t test:0 -x20 -y24 || exit 1
|
||||
|
||||
# Exercise widening, narrowing, and equal widths with no source history.
|
||||
for pair in '0 1' '1 0' '1 2'; do
|
||||
set -- $pair
|
||||
if [ "$2" = 2 ]; then
|
||||
$TMUX new-window -t test:2 'sleep 100' || exit 1
|
||||
$TMUX resize-window -t test:2 -x80 -y24 || exit 1
|
||||
fi
|
||||
source=test:$1.0
|
||||
target=test:$2.0
|
||||
[ "$($TMUX display-message -p -t "$source" '#{history_size}')" = 0 ] ||
|
||||
fail "source has unexpected history"
|
||||
$TMUX copy-mode -s "$source" -t "$target" || exit 1
|
||||
$TMUX has-session -t test || fail "server died copying blank source"
|
||||
[ "$($TMUX display-message -p -t "$target" \
|
||||
'#{pane_in_mode} #{copy_cursor_x} #{copy_cursor_y}')" = '1 0 0' ] ||
|
||||
fail "blank source did not enter copy mode at the first cell"
|
||||
$TMUX send-keys -t "$target" -X cancel || exit 1
|
||||
done
|
||||
|
||||
# Real content still trims trailing empty lines, clamping the cursor to beta.
|
||||
$TMUX respawn-pane -k -t test:0.0 \
|
||||
"printf 'alpha\r\nbeta\r\n\r\n\r\n'; exec sleep 100" || exit 1
|
||||
i=0
|
||||
while [ "$($TMUX display-message -p -t test:0.0 '#{cursor_y}')" != 4 ]; do
|
||||
i=$((i + 1))
|
||||
[ "$i" -lt 10 ] || fail "source output did not arrive"
|
||||
sleep 1
|
||||
done
|
||||
$TMUX copy-mode -s test:0.0 -t test:1.0 || exit 1
|
||||
[ "$($TMUX display-message -p -t test:1.0 \
|
||||
'#{pane_in_mode} #{copy_cursor_y} #{copy_cursor_line}')" = '1 1 beta' ] ||
|
||||
fail "nonblank source content or trailing-line trimming changed"
|
||||
|
||||
exit 0
|
||||
@@ -7,8 +7,6 @@ TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
trap '$TMUX kill-server 2>/dev/null' 0
|
||||
trap 'exit 1' 1 2 15
|
||||
|
||||
# test_format $format $expected_result
|
||||
test_format()
|
||||
|
||||
@@ -18,24 +18,6 @@ export TZ LANG LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
FIFO1="${TMPDIR:-/tmp}/fmt-l-$$-1"
|
||||
FIFO2="${TMPDIR:-/tmp}/fmt-l-$$-2"
|
||||
HOLD1=
|
||||
HOLD2=
|
||||
CC1=
|
||||
CC2=
|
||||
|
||||
cleanup()
|
||||
{
|
||||
for pid in $HOLD1 $HOLD2 $CC1 $CC2; do
|
||||
kill "$pid" 2>/dev/null
|
||||
wait "$pid" 2>/dev/null
|
||||
done
|
||||
$TMUX kill-server 2>/dev/null
|
||||
rm -f "$FIFO1" "$FIFO2"
|
||||
}
|
||||
trap cleanup 0
|
||||
trap 'exit 1' 1 2 15
|
||||
|
||||
ESC=$(printf '\033')
|
||||
|
||||
@@ -597,6 +579,8 @@ assert_alive "verbose loop expansion"
|
||||
|
||||
# L loops over attached clients. Attach two control-mode clients, each held
|
||||
# open by a background process keeping a FIFO's write end open.
|
||||
FIFO1="${TMPDIR:-/tmp}/fmt-l-$$-1"
|
||||
FIFO2="${TMPDIR:-/tmp}/fmt-l-$$-2"
|
||||
rm -f "$FIFO1" "$FIFO2"
|
||||
mkfifo "$FIFO1" "$FIFO2" || exit 1
|
||||
# Hold the write ends open so the control clients stay attached.
|
||||
@@ -621,9 +605,9 @@ test_format "#{L/nr:x}" "xx"
|
||||
test_format "#{L/r:x}" "xx"
|
||||
# Now detach one and confirm the count drops to one.
|
||||
kill $HOLD2 2>/dev/null
|
||||
wait $HOLD2 2>/dev/null
|
||||
HOLD2=
|
||||
sleep 1
|
||||
test_format "#{L:x}" "x"
|
||||
kill $HOLD1 $CC1 $CC2 2>/dev/null
|
||||
rm -f "$FIFO1" "$FIFO2"
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -7,8 +7,6 @@ TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
trap '$TMUX kill-server 2>/dev/null' 0
|
||||
trap 'exit 1' 1 2 15
|
||||
|
||||
# test_format $format $expected_result
|
||||
test_format()
|
||||
|
||||
@@ -76,14 +76,14 @@ $TMUX set-hook -g session-closed \
|
||||
fail "set-hook session-closed failed"
|
||||
|
||||
# The only pane of the only window of a session exits: pane-exited, then
|
||||
# session-closed, then window-unlinked, each seeing the dead object in the
|
||||
# window-unlinked, then session-closed, each seeing the dead object in the
|
||||
# hook formats.
|
||||
pane=$($TMUX new -d -s doomed -n dwin -P -F '#{pane_id}' 'true') ||
|
||||
fail "new-session doomed failed"
|
||||
wait_for @log \
|
||||
"|pane-exited:$pane|session-closed:doomed|window-unlinked:doomed:dwin"
|
||||
"|pane-exited:$pane|window-unlinked:doomed:dwin|session-closed:doomed"
|
||||
assert_unchanged @log \
|
||||
"|pane-exited:$pane|session-closed:doomed|window-unlinked:doomed:dwin"
|
||||
"|pane-exited:$pane|window-unlinked:doomed:dwin|session-closed:doomed"
|
||||
|
||||
# The dead pane, window and session cannot be used as targets but the
|
||||
# server survives.
|
||||
@@ -110,14 +110,14 @@ $TMUX set-hook -g pane-exited \
|
||||
'set -gF @log "#{@log}|pane-exited:#{hook_pane}"' ||
|
||||
fail "restore pane-exited hook failed"
|
||||
|
||||
# kill-window on the last window: session-closed then window-unlinked but
|
||||
# kill-window on the last window: window-unlinked then session-closed but
|
||||
# no pane-exited for the panes in the killed window.
|
||||
$TMUX set -g @log '' || fail "reset @log failed"
|
||||
$TMUX new -d -s doomed2 -n dwin2 || fail "new-session doomed2 failed"
|
||||
$TMUX splitw -d -t doomed2:0 || fail "split-window doomed2 failed"
|
||||
$TMUX kill-window -t doomed2:0 || fail "kill-window failed"
|
||||
wait_for @log '|session-closed:doomed2|window-unlinked:doomed2:dwin2'
|
||||
assert_unchanged @log '|session-closed:doomed2|window-unlinked:doomed2:dwin2'
|
||||
wait_for @log '|window-unlinked:doomed2:dwin2|session-closed:doomed2'
|
||||
assert_unchanged @log '|window-unlinked:doomed2:dwin2|session-closed:doomed2'
|
||||
$TMUX has -t main || fail "server died after kill-window chain"
|
||||
|
||||
# kill-session: session-closed fires first, then window-unlinked for its
|
||||
|
||||
@@ -12,8 +12,7 @@ $TMUX kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp)
|
||||
OUT=$(mktemp)
|
||||
trap 'rm -f "$TMP" "$OUT"; $TMUX kill-server 2>/dev/null' 0
|
||||
trap 'exit 1' 1 2 15
|
||||
trap "rm -f $TMP $OUT" 0 1 15
|
||||
|
||||
cat <<EOF >$TMP
|
||||
if 'true' 'wibble wobble'
|
||||
|
||||
@@ -4,9 +4,6 @@ TERM=screen
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
|
||||
# Keep panes alive until the next case or cleanup, without reading replies.
|
||||
INPUT_HOLD='while :; do sleep 3600; done'
|
||||
|
||||
TMP=$(mktemp)
|
||||
EXP=$(mktemp)
|
||||
trap 'rm -f "$TMP" "$EXP"; $TMUX kill-server 2>/dev/null' 0 1 15
|
||||
@@ -40,10 +37,10 @@ start_pane_hlimit()
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
sleep 0.1
|
||||
$TMUX new-session -d -x 1 -y 1 -s test-setup "$INPUT_HOLD" || exit 1
|
||||
$TMUX new-session -d -x 1 -y 1 -s test-setup "sleep 2" || exit 1
|
||||
$TMUX set-option -g history-limit "$hlimit" || exit 1
|
||||
$TMUX new-session -d -x "$sx" -y "$sy" -s "$name" \
|
||||
"printf '$seq'; $INPUT_HOLD" || exit 1
|
||||
"printf '$seq'; sleep 2" || exit 1
|
||||
$TMUX kill-session -t test-setup
|
||||
sleep 0.3
|
||||
}
|
||||
|
||||
@@ -22,19 +22,7 @@ assert_key () {
|
||||
clear-history -t$W \; \
|
||||
send-keys -t$W "$key" 'EOL' || exit 1
|
||||
|
||||
# cat echoes the keys back asynchronously, so wait for the EOL marker
|
||||
# to reach the pane instead of capturing straight away.
|
||||
i=0
|
||||
while [ $i -lt 50 ]; do
|
||||
screen=$($TMUX capturep -pt$W)
|
||||
case "$screen" in
|
||||
*EOL*) break ;;
|
||||
esac
|
||||
i=$((i + 1))
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
actual_code=$(printf '%s\n' "$screen" | \
|
||||
actual_code=$($TMUX capturep -pt$W | \
|
||||
head -1 | \
|
||||
sed -e 's/EOL.*$//')
|
||||
|
||||
|
||||
@@ -2,38 +2,6 @@
|
||||
|
||||
. ./input-common.inc
|
||||
|
||||
# Wait for the terminator and following text to reach the parser.
|
||||
check_discard()
|
||||
{
|
||||
name=$1
|
||||
printf 'OK\n' >"$EXP"
|
||||
i=0
|
||||
while [ "$i" -lt 300 ]; do
|
||||
capture_grid "$name" >"$TMP"
|
||||
cmp -s "$TMP" "$EXP" && return 0
|
||||
sleep 0.05
|
||||
i=$((i + 1))
|
||||
done
|
||||
fail "$name (timed out waiting for discard)"
|
||||
}
|
||||
|
||||
# The missing-terminator timer may expire before the string limit is reached
|
||||
# on a slow build. Clear any payload printed after the timeout, then check
|
||||
# that the string did not change the title and normal output has resumed.
|
||||
test_discard()
|
||||
{
|
||||
name=$1
|
||||
prefix=$2
|
||||
start_cmd "$name" 8 3 "$INPUT_HOLD"
|
||||
$TMUX select-pane -T discard-test || exit 1
|
||||
$TMUX respawn-pane -k \
|
||||
"perl -e 'print qq{$prefix}, q{x} x 1100000, qq{\e\\\\\e[H\e[2JOK}'; $INPUT_HOLD" || exit 1
|
||||
check_discard "$name"
|
||||
$TMUX display-message -p -t "$name:" '#{pane_title}' >"$TMP" || exit 1
|
||||
printf 'discard-test\n' >"$EXP"
|
||||
cmp "$TMP" "$EXP" || fail "$name title"
|
||||
}
|
||||
|
||||
start_cmd csi-param-discard 8 3 \
|
||||
"perl -e 'print qq{\e[}, q{1} x 80, qq{\030OK}'; sleep 2"
|
||||
check_capture csi-param-discard 'OK'
|
||||
@@ -42,8 +10,13 @@ start_cmd csi-interm-discard 8 3 \
|
||||
"perl -e 'print qq{\e[ \030OK}'; sleep 2"
|
||||
check_capture csi-interm-discard 'OK'
|
||||
|
||||
test_discard osc-discard '\e]2;'
|
||||
test_discard apc-discard '\e_'
|
||||
start_cmd osc-discard 8 3 \
|
||||
"perl -e 'print qq{\e]2;}, q{x} x 1100000, qq{\e\\\\OK}'; sleep 2"
|
||||
check_capture osc-discard 'OK'
|
||||
|
||||
start_cmd apc-discard 8 3 \
|
||||
"perl -e 'print qq{\e_}, q{x} x 1100000, qq{\e\\\\OK}'; sleep 2"
|
||||
check_capture apc-discard 'OK'
|
||||
|
||||
start_pane unknown-csi 8 3 '\033[?9999zOK'
|
||||
check_capture unknown-csi 'OK'
|
||||
|
||||
@@ -51,7 +51,7 @@ $TMUX kill-server 2>/dev/null
|
||||
sleep 0.1
|
||||
$TMUX new-session -d -x 5 -y 3 -s history \; \
|
||||
set-option -g history-limit 3 \; \
|
||||
respawn-pane -k "printf '01\n02\n03\n04\n05\n06'; $INPUT_HOLD" || exit 1
|
||||
respawn-pane -k "printf '01\n02\n03\n04\n05\n06'; sleep 2" || exit 1
|
||||
sleep 0.3
|
||||
$TMUX capture-pane -pN -t history: -S - -E - | normalize_capture >"$TMP"
|
||||
printf "%s\n" '01
|
||||
|
||||
@@ -377,7 +377,10 @@ must_equal 'Layout after select-pane back' "$(layout L:two)" "$SPLIT"
|
||||
|
||||
# With nothing zoomed the two layout formats agree.
|
||||
#
|
||||
# Zoomed layouts are checked below with floating panes.
|
||||
# The zoomed case is deliberately not covered here. While a pane is zoomed
|
||||
# #{window_layout} dumps the saved (unzoomed) layout and
|
||||
# #{window_visible_layout} the zoomed one, but that depends on how zooming
|
||||
# stashes the layout root rather than on anything in layout-custom.c.
|
||||
must_equal 'Visible layout' "$(visible_layout L:two)" "$SPLIT"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -701,42 +704,6 @@ must_contain 'Floating layout back z-index' "$floating" '"z":1'
|
||||
check_ok select-layout -t L:float "$floating"
|
||||
must_equal 'Floating layout after round trip' "$(raw_layout L:float)" "$floating"
|
||||
|
||||
# A dump taken while zoomed must retain the unzoomed floating z-indexes.
|
||||
# Check hidden floats, floats above zoom, and a mixture of the two.
|
||||
for flags in '' A mixed; do
|
||||
check_ok new-window -d -t L: -n zoom
|
||||
zt=$($TMUX display-message -p -t L:zoom '#{pane_id}')
|
||||
check_ok split-window -d -h -t "$zt"
|
||||
case "$flags" in
|
||||
A|mixed) first=-Ad ;;
|
||||
*) first=-d ;;
|
||||
esac
|
||||
case "$flags" in
|
||||
A) second=-Ad ;;
|
||||
*) second=-d ;;
|
||||
esac
|
||||
check_ok new-pane "$first" -t "$zt" -x 20 -y 6 ''
|
||||
check_ok new-pane "$second" -t "$zt" -x 30 -y 8 ''
|
||||
for pane in 0 2 3; do
|
||||
check_ok select-pane -t "L:zoom.$pane"
|
||||
before=$(raw_layout L:zoom)
|
||||
legacy=$(v1_layout L:zoom)
|
||||
check_ok resize-pane -Z -t "L:zoom.$pane"
|
||||
during=$(raw_layout L:zoom)
|
||||
must_equal 'Layout while zoomed' "$during" "$before"
|
||||
must_equal 'Legacy layout while zoomed' \
|
||||
"$(v1_layout L:zoom)" "$legacy"
|
||||
must_equal 'Zoom after dumping layout' \
|
||||
"$($TMUX display-message -p -t L:zoom '#{window_zoomed_flag}')" 1
|
||||
must_differ 'Visible layout while zoomed' \
|
||||
"$(visible_layout L:zoom)" "$(layout L:zoom)"
|
||||
check_ok select-layout -t L:zoom "$during"
|
||||
must_equal 'Round trip from zoomed layout' \
|
||||
"$(raw_layout L:zoom)" "$before"
|
||||
done
|
||||
check_ok kill-window -t L:zoom
|
||||
done
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Floating panes and the legacy (v1) format.
|
||||
#
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Chooser menus are centred on the mouse using their displayed width. A
|
||||
# hidden title must not move a borderless menu away from the mouse.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$TMUX kill-server >/dev/null 2>&1
|
||||
$TMUX2 kill-server >/dev/null 2>&1
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
$TMUX new-session -d -s short -x 100 -y 30 'sleep 100' || exit 1
|
||||
$TMUX set -g mouse on || exit 1
|
||||
$TMUX set -g status off || exit 1
|
||||
$TMUX2 new-session -d -x 100 -y 30 "$TMUX attach" || exit 1
|
||||
sleep 1
|
||||
|
||||
for name in short aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; do
|
||||
$TMUX rename-session "$name" || exit 1
|
||||
for lines in none single padded; do
|
||||
$TMUX set -g menu-border-lines "$lines" || exit 1
|
||||
$TMUX choose-tree -s || exit 1
|
||||
sleep 1
|
||||
|
||||
# Right-button press at window (60, 0), away from either edge.
|
||||
seq=$(printf '\033[<2;61;1M')
|
||||
$TMUX2 send-keys -l "$seq" || exit 1
|
||||
sleep 1
|
||||
|
||||
row=2
|
||||
column=54
|
||||
if [ "$lines" = none ]; then
|
||||
row=1
|
||||
elif [ "$name" != short ]; then
|
||||
column=31
|
||||
fi
|
||||
text=$($TMUX2 capture-pane -p | awk -v row="$row" \
|
||||
-v column="$column" 'NR == row {
|
||||
# Keep byte offsets equal to columns with non-Unicode awk.
|
||||
gsub(/│/, "|")
|
||||
print substr($0, column, 7)
|
||||
}')
|
||||
[ "$text" = 'Select ' ] || \
|
||||
fail "$lines menu for $name: expected Select at ($column, $row), got '$text'"
|
||||
|
||||
# Close the menu, release the button, then leave the chooser.
|
||||
$TMUX2 send-keys Escape || exit 1
|
||||
seq=$(printf '\033[<2;61;1m')
|
||||
$TMUX2 send-keys -l "$seq" || exit 1
|
||||
$TMUX2 send-keys q || exit 1
|
||||
sleep 1
|
||||
done
|
||||
done
|
||||
|
||||
exit 0
|
||||
@@ -15,7 +15,7 @@ PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
TMUX="$TEST_TMUX -Ltest$$"
|
||||
TMUX="$TEST_TMUX -Ltest"
|
||||
$TMUX kill-server 2>/dev/null
|
||||
|
||||
DIR=$(mktemp -d)
|
||||
|
||||
@@ -22,26 +22,14 @@ check_directory()
|
||||
fi
|
||||
}
|
||||
|
||||
# The start path is available immediately, before the child is scheduled.
|
||||
# Use it to test the format context in the same command queue as creation.
|
||||
# Expand the current pane's directory in the same command queue as creation.
|
||||
$TMUX new-session -d -s test -c "$TMP/first" 'sleep 60' \; \
|
||||
run-shell -c '#{pane_start_path}' "pwd >'$TMP/out'" || exit 1
|
||||
run-shell -c '#{pane_current_path}' "pwd >'$TMP/out'" || exit 1
|
||||
check_directory "$TMP/first"
|
||||
|
||||
# An explicit target must supply the format context, including with a delay.
|
||||
pane=$($TMUX new-window -d -P -F '#{pane_id}' -t test \
|
||||
-c "$TMP/second dir" 'sleep 60') || exit 1
|
||||
# The current path depends on the operating system finding the child process.
|
||||
i=0
|
||||
while [ "$($TMUX display-message -p -t "$pane" '#{pane_current_path}')" != \
|
||||
"$TMP/second dir" ]; do
|
||||
if [ "$i" -ge 100 ]; then
|
||||
echo "Timed out waiting for pane current directory"
|
||||
exit 1
|
||||
fi
|
||||
sleep 0.05
|
||||
i=$((i + 1))
|
||||
done
|
||||
$TMUX run-shell -t "$pane" -d 0.1 -c '#{pane_current_path}' \
|
||||
"pwd >'$TMP/out'" || exit 1
|
||||
check_directory "$TMP/second dir"
|
||||
|
||||
@@ -106,28 +106,9 @@ compare menu-over-split
|
||||
|
||||
# Menu with no border lines.
|
||||
setup 40 14
|
||||
$TMUX2 display-menu -T "This title must not reserve width" -C 1 \
|
||||
-b none -x6 -y8 \
|
||||
"Alpha item" a "" \
|
||||
"Beta item" b "" \
|
||||
"" "" "" \
|
||||
"Gamma item" g "" || exit 1
|
||||
sleep 1
|
||||
menu -b none -x6 -y8
|
||||
compare menu-noborder
|
||||
|
||||
# Menu border style follows the explicitly targeted window, not the current
|
||||
# window when a different pane is selected.
|
||||
setup 40 14
|
||||
$TMUX2 set menu-border-lines none || exit 1
|
||||
$TMUX2 neww || exit 1
|
||||
$TMUX2 display-menu -t%0 -T "Menu" -C 1 \
|
||||
"Alpha item" a "" \
|
||||
"Beta item" b "" \
|
||||
"" "" "" \
|
||||
"Gamma item" g "" || exit 1
|
||||
$TMUX2 selectw -t%0 || exit 1
|
||||
compare menu-target-window-noborder
|
||||
|
||||
# Menu with double border lines.
|
||||
setup 40 14
|
||||
menu -b double -x6 -y8
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
MENU00 abcdefghij
|
||||
MENU01 abcdefghij
|
||||
MENU02 abcdefghij
|
||||
MENU03 abcdefghij
|
||||
MENU04[38;5;250m[48;5;235m Alpha item (a) [39m[49m
|
||||
MENU05[38;5;16m[48;5;220m Beta item (b) [39m[49m
|
||||
MENU06[38;5;45m[48;5;235m [39m[49m
|
||||
MENU07[38;5;250m[48;5;235m Gamma item (g) [39m[49m
|
||||
MENU02[38;5;45m[48;5;235m Menu [39m[49m
|
||||
MENU03[38;5;45m[48;5;235m [38;5;250m Alpha item (a) [38;5;45m [39m[49m
|
||||
MENU04[38;5;45m[48;5;235m [38;5;16m[48;5;220m Beta item (b) [38;5;45m[48;5;235m [39m[49m
|
||||
MENU05[38;5;45m[48;5;235m [39m[49m
|
||||
MENU06[38;5;45m[48;5;235m [38;5;250m Gamma item (g) [38;5;45m [39m[49m
|
||||
MENU07[38;5;45m[48;5;235m [39m[49m
|
||||
MENU08 abcdefghij
|
||||
MENU09 abcdefghij
|
||||
MENU10 abcdefghij
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
MENU00 abcdefghij
|
||||
MENU01 abcdefghij
|
||||
MENU02 abcdefghij
|
||||
MENU03 abcdefghij
|
||||
MENU04 abcd[38;5;250m[48;5;235m Alpha item (a) [39m[49m
|
||||
MENU05 abcd[38;5;16m[48;5;220m Beta item (b) [39m[49m
|
||||
MENU06 abcd[38;5;45m[48;5;235m [39m[49m
|
||||
MENU07 abcd[38;5;250m[48;5;235m Gamma item (g) [39m[49m
|
||||
MENU08 abcdefghij
|
||||
MENU09 abcdefghij
|
||||
MENU10 abcdefghij
|
||||
MENU11 abcdefghij
|
||||
MENU12 abcdefghij
|
||||
@@ -95,8 +95,7 @@ layout_tee_down() { # top/bottom, bottom split: a top tee
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
# Keep the anchor window alive until cleanup, even on slow test runs.
|
||||
$TMUX2 new -d -x40 -y14 'exec cat' || exit 1
|
||||
$TMUX2 new -d -x40 -y14 "sh -c 'exec sleep 100'" || exit 1
|
||||
$TMUX2 set -g status off || exit 1
|
||||
$TMUX2 set -g window-size manual || exit 1
|
||||
$TMUX2 set -g pane-border-format " #{pane_index} " || exit 1
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# When only some lines are redrawn after a synchronized update, a line
|
||||
# following a wrapped line must be drawn at its own position, not where the
|
||||
# cursor happens to be.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
|
||||
DIR=$(mktemp -d) || exit 1
|
||||
TMUX_TMPDIR=$DIR
|
||||
export TMUX_TMPDIR
|
||||
|
||||
INNER="$TEST_TMUX -Li$$ -f/dev/null"
|
||||
OUTER="$TEST_TMUX -Lo$$ -f/dev/null"
|
||||
CONTROL=$DIR/control
|
||||
EMITTER=$DIR/emitter.pl
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$OUTER kill-server 2>/dev/null
|
||||
$INNER kill-server 2>/dev/null
|
||||
rm -rf "$DIR"
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
wait_for_file()
|
||||
{
|
||||
i=0
|
||||
while [ "$i" -lt 50 ] && [ ! -e "$1" ]; do
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
[ -e "$1" ] || fail "$2"
|
||||
}
|
||||
|
||||
wait_for_client()
|
||||
{
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
$INNER list-clients -F '#{client_termfeatures}' 2>/dev/null |
|
||||
grep -q 'sync' && return 0
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
fail "sync-capable client did not attach"
|
||||
}
|
||||
|
||||
cat >"$EMITTER" <<'PERL'
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $control = $ENV{CONTROL};
|
||||
(my $dir = $control) =~ s{/[^/]+$}{};
|
||||
|
||||
# Fill the screen with 80 column lines and no newlines so every line wraps.
|
||||
my $out = "\e[H\e[2J";
|
||||
for my $row (1 .. 24) {
|
||||
$out .= substr(sprintf("ROW%02d_", $row) . ('x' x 80), 0, 80);
|
||||
}
|
||||
syswrite STDOUT, $out . "\e[1;1H";
|
||||
|
||||
open my $painted, '>', "$dir/painted" or die "$dir/painted: $!\n";
|
||||
close $painted;
|
||||
while (!-e $control) {
|
||||
select undef, undef, undef, 0.01;
|
||||
}
|
||||
|
||||
# Change rows 2 and 6 in one synchronized update.
|
||||
my $frame = "\e[?2026h" .
|
||||
"\e[2;1H" . substr("NEW02_" . ('#' x 80), 0, 80) .
|
||||
"\e[6;1H" . substr("NEW06_" . ('%' x 80), 0, 80) .
|
||||
"\e[24;1H" .
|
||||
"\e[?2026l";
|
||||
my $written = syswrite STDOUT, $frame;
|
||||
die "short synchronized frame write\n"
|
||||
unless defined $written && $written == length $frame;
|
||||
open my $done, '>', "$dir/done" or die "$dir/done: $!\n";
|
||||
close $done;
|
||||
select undef, undef, undef, 3;
|
||||
PERL
|
||||
|
||||
$INNER new-session -d -s inner -x 80 -y 24 \
|
||||
"CONTROL='$CONTROL' perl '$EMITTER'" || exit 1
|
||||
$INNER set-option -g status off || exit 1
|
||||
$INNER set-option -g window-size manual || exit 1
|
||||
$INNER set-option -as terminal-features '*:sync' || exit 1
|
||||
|
||||
$OUTER new-session -d -s outer -x 80 -y 24 \
|
||||
"$TEST_TMUX -Li$$ -f/dev/null attach-session -t inner" ||
|
||||
exit 1
|
||||
$OUTER set-option -g status off || exit 1
|
||||
$OUTER set-option -g window-size manual || exit 1
|
||||
wait_for_client
|
||||
|
||||
wait_for_file "$DIR/painted" "application did not paint"
|
||||
sleep 1
|
||||
: >"$CONTROL"
|
||||
wait_for_file "$DIR/done" "application did not finish"
|
||||
sleep 1
|
||||
|
||||
$OUTER capture-pane -p -t outer:0.0 >"$DIR/screen" || exit 1
|
||||
sed -n 2p "$DIR/screen" | grep -q '^NEW02_#' || fail "row 2 not redrawn"
|
||||
sed -n 3p "$DIR/screen" | grep -q '^ROW03_x' || fail "row 3 overwritten"
|
||||
sed -n 6p "$DIR/screen" | grep -q '^NEW06_%' || fail "row 6 not redrawn"
|
||||
exit 0
|
||||
@@ -9,37 +9,14 @@ $TMUX kill-server 2>/dev/null
|
||||
TMUX2="$TEST_TMUX -LtestB$$ -f/dev/null"
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
TMP=$(mktemp) || exit 1
|
||||
prompt_pid=
|
||||
|
||||
cleanup () {
|
||||
if [ -n "$prompt_pid" ]; then
|
||||
kill "$prompt_pid" 2>/dev/null
|
||||
wait "$prompt_pid" 2>/dev/null
|
||||
fi
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
rm -f "$TMP"
|
||||
}
|
||||
trap cleanup 0
|
||||
trap 'exit 1' 1 2 15
|
||||
|
||||
fail () {
|
||||
echo "[FAIL] $*" >&2
|
||||
exit 1
|
||||
}
|
||||
TMP=$(mktemp)
|
||||
trap "rm -f $TMP" 0 1 15
|
||||
|
||||
$TMUX2 -f/dev/null new -d || exit 1
|
||||
$TMUX -f/dev/null new -d "$TMUX2 attach" || exit 1
|
||||
i=0
|
||||
while [ -z "$($TMUX2 list-clients -F '#{client_name}')" ]; do
|
||||
[ "$i" -lt 100 ] || fail "inner client did not attach"
|
||||
sleep 0.05
|
||||
i=$((i + 1))
|
||||
done
|
||||
sleep 1
|
||||
|
||||
exit_status=0
|
||||
assertion=0
|
||||
|
||||
format_string () {
|
||||
case $1 in
|
||||
@@ -57,33 +34,12 @@ assert_key () {
|
||||
expected_name=$2
|
||||
format_string=$(format_string "$expected_name")
|
||||
|
||||
# Use a different prompt each time so a stale redraw cannot look ready.
|
||||
assertion=$((assertion + 1))
|
||||
prompt="tty-keys-$assertion:"
|
||||
$TMUX2 command-prompt -k -p "$prompt" \
|
||||
'display-message -pl '"$format_string" > "$TMP" &
|
||||
prompt_pid=$!
|
||||
i=0
|
||||
while ! $TMUX capture-pane -p | grep -Fq "$prompt"; do
|
||||
kill -0 "$prompt_pid" 2>/dev/null || \
|
||||
fail "$keys -> $expected_name: prompt exited before becoming ready"
|
||||
[ "$i" -lt 100 ] || \
|
||||
fail "$keys -> $expected_name: timed out waiting for prompt"
|
||||
sleep 0.05
|
||||
i=$((i + 1))
|
||||
done
|
||||
$TMUX2 command-prompt -k 'display-message -pl '"$format_string" > "$TMP" &
|
||||
sleep 0.05
|
||||
|
||||
$TMUX send-keys $keys || fail "could not send $keys"
|
||||
$TMUX send-keys $keys
|
||||
|
||||
i=0
|
||||
while kill -0 "$prompt_pid" 2>/dev/null; do
|
||||
[ "$i" -lt 100 ] || \
|
||||
fail "$keys -> $expected_name: timed out waiting for key"
|
||||
sleep 0.05
|
||||
i=$((i + 1))
|
||||
done
|
||||
wait "$prompt_pid" || fail "$keys -> $expected_name: prompt failed"
|
||||
prompt_pid=
|
||||
wait
|
||||
|
||||
keys=$(printf '%s' "$keys" | sed -e 's/Escape/\\\\033/g' | tr -d '[:space:]')
|
||||
actual_name=$(tr -d '[:space:]' < "$TMP")
|
||||
@@ -409,4 +365,7 @@ assert_key 'Escape [32;2u' 'S-Space'
|
||||
assert_key 'Escape [9;5u' 'C-Tab'
|
||||
assert_key 'Escape [1;5Z' 'C-S-Tab'
|
||||
|
||||
$TMUX kill-server 2>/dev/null
|
||||
$TMUX2 kill-server 2>/dev/null
|
||||
|
||||
exit $exit_status
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A pane that doesn't span the terminal's full width - because
|
||||
# pane-scrollbars is on (the scrollbar occupies a column) or the pane is
|
||||
# one of a side-by-side split - needs DECSLRM (left/right margin) support
|
||||
# to use the fast native-scroll path (tty_cmd_linefeed()/scrollup()/
|
||||
# scrolldown()/reverseindex(), tty.c:
|
||||
# "(!tty_full_width(tty, ctx) && !tty_use_margin(tty))"). Without it, every
|
||||
# single scroll falls back to tty_redraw_region()'s full manual repaint of
|
||||
# the whole region - a real, confirmed source of flicker (and, separately,
|
||||
# of image content not surviving a scroll in branches with image support).
|
||||
#
|
||||
# tty_default_features() (tty-features.c) grants the "margins" feature to
|
||||
# several terminals it can positively identify via XTVERSION/DA2 (mintty,
|
||||
# iTerm2, WezTerm, ghostty, XTerm-as-VT420) - this checks the actual
|
||||
# server-side scroll decision via the -vv log for the underlying mechanism
|
||||
# those table entries all rely on, using the terminal-features option
|
||||
# directly (which any of them - or a user's own terminal-overrides -
|
||||
# ultimately feed into) rather than simulating any one terminal's
|
||||
# identification handshake.
|
||||
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
LC_ALL=C.UTF-8
|
||||
export PATH TERM LC_ALL
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
|
||||
DIR=$(mktemp -d) || exit 1
|
||||
cd "$DIR" || exit 1
|
||||
INNER="$TEST_TMUX -vv -Lmarginsscrollbar-inner-$$ -f/dev/null"
|
||||
OUTER="$TEST_TMUX -Lmarginsscrollbar-outer-$$ -f/dev/null"
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
cleanup()
|
||||
{
|
||||
$OUTER kill-server 2>/dev/null
|
||||
$INNER kill-server 2>/dev/null
|
||||
cd /
|
||||
rm -rf "$DIR"
|
||||
}
|
||||
trap cleanup 0 1 15
|
||||
|
||||
wait_for_client()
|
||||
{
|
||||
i=0
|
||||
while [ "$i" -lt 50 ]; do
|
||||
CLIENT=$($INNER list-clients -F '#{client_name}' 2>/dev/null)
|
||||
[ -n "$CLIENT" ] && return 0
|
||||
sleep 0.1
|
||||
i=$((i + 1))
|
||||
done
|
||||
fail "inner client did not attach"
|
||||
}
|
||||
|
||||
run_scroll_phase()
|
||||
{
|
||||
label=$1
|
||||
margins=$2
|
||||
|
||||
rm -f tmux-server*.log
|
||||
|
||||
$INNER new-session -d -s inner -x 40 -y 6 'exec sh' || exit 1
|
||||
$INNER set -g status off || exit 1
|
||||
$INNER set -g window-size manual || exit 1
|
||||
$INNER set -g pane-scrollbars on || exit 1
|
||||
if [ "$margins" = "on" ]; then
|
||||
$INNER set -as terminal-features ',*:margins' || exit 1
|
||||
fi
|
||||
|
||||
$OUTER new-session -d -x 40 -y 6 || exit 1
|
||||
OUTERPANE=$($OUTER list-panes -F '#{pane_id}') || exit 1
|
||||
$OUTER set -g status off || exit 1
|
||||
$OUTER set -g window-size manual || exit 1
|
||||
$OUTER set -g default-terminal screen-256color || exit 1
|
||||
$OUTER send-keys -t "$OUTERPANE" -l "$INNER attach -t inner" || exit 1
|
||||
$OUTER send-keys -t "$OUTERPANE" Enter || exit 1
|
||||
sleep 1
|
||||
|
||||
wait_for_client
|
||||
|
||||
i=0
|
||||
while [ "$i" -lt 8 ]; do
|
||||
$INNER send-keys -t inner Enter || exit 1
|
||||
sleep 0.2
|
||||
i=$((i + 1))
|
||||
done
|
||||
sleep 0.3
|
||||
|
||||
LOG=$(ls tmux-server*.log 2>/dev/null | head -1)
|
||||
[ -n "$LOG" ] || fail "$label: sanity: no server -vv log was produced"
|
||||
|
||||
n=$(grep -c "tty_redraw_region.*large region redraw" "$LOG")
|
||||
|
||||
$OUTER kill-server 2>/dev/null
|
||||
$INNER kill-server 2>/dev/null
|
||||
|
||||
echo "$n"
|
||||
}
|
||||
|
||||
# Phase 1: margins granted - must never fall back to a full region redraw.
|
||||
n_with=$(run_scroll_phase "with margins" "on")
|
||||
[ "$n_with" -eq 0 ] ||
|
||||
fail "with margins granted, scrolling a scrollbar-enabled pane still fell back to a full region redraw ($n_with times)"
|
||||
|
||||
# Phase 2: sanity check - without margins, the same scenario must actually
|
||||
# hit the fallback, proving phase 1 wasn't accidentally trivial.
|
||||
n_without=$(run_scroll_phase "without margins" "off")
|
||||
[ "$n_without" -gt 0 ] ||
|
||||
fail "sanity: without margins, scrolling a scrollbar-enabled pane never fell back to a full region redraw - this scenario no longer exercises the bug this test checks for"
|
||||
|
||||
exit 0
|
||||
@@ -1,164 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# A disconnected waiter must release both its wait and its command queue.
|
||||
PATH=/bin:/usr/bin
|
||||
TERM=screen
|
||||
export TERM
|
||||
|
||||
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
|
||||
OUT=$(mktemp -d)
|
||||
TMUX="$TEST_TMUX -S$OUT/socket -f/dev/null"
|
||||
pids=
|
||||
|
||||
cleanup()
|
||||
{
|
||||
for pid in $pids; do
|
||||
kill "$pid" 2>/dev/null || true
|
||||
done
|
||||
$TMUX kill-server 2>/dev/null || true
|
||||
rm -rf "$OUT"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
fail()
|
||||
{
|
||||
echo "$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
wait_list()
|
||||
{
|
||||
expected=$1
|
||||
shift
|
||||
i=0
|
||||
while [ $i -lt 100 ]; do
|
||||
value=$($TMUX wait-for -l "$@") || fail "list waiters failed"
|
||||
[ "$value" = "$expected" ] && return
|
||||
i=$((i + 1))
|
||||
sleep 0.05
|
||||
done
|
||||
fail "expected waiters '$expected', got '$value'"
|
||||
}
|
||||
|
||||
wait_free()
|
||||
{
|
||||
client_pid=$1
|
||||
i=0
|
||||
while [ $i -lt 100 ]; do
|
||||
awk -v pid="$client_pid" '
|
||||
$4 == "IDENTIFY_CLIENTPID" && $5 == pid { address = $3 }
|
||||
address != "" && $2 == "free" && $3 == "client" &&
|
||||
$4 == address && $5 == "(0" { freed = 1 }
|
||||
END { exit !freed }
|
||||
' "$OUT"/tmux-server-*.log && return
|
||||
i=$((i + 1))
|
||||
sleep 0.05
|
||||
done
|
||||
fail "client $client_pid was not freed"
|
||||
}
|
||||
|
||||
cd "$OUT" || exit 1
|
||||
$TMUX -vv new-session -d -s test || fail "new-session failed"
|
||||
$TMUX set -g @continued 0 || fail "set option failed"
|
||||
|
||||
for signal in TERM KILL; do
|
||||
for kind in channel lock event; do
|
||||
name="$kind-$signal"
|
||||
case $kind in
|
||||
channel) args="$name"; list_args="$name" ;;
|
||||
lock)
|
||||
$TMUX wait-for -L "$name" || fail "lock failed"
|
||||
args="-L $name"; list_args="$name"
|
||||
;;
|
||||
event) args="-E @$name"; list_args="-E @$name" ;;
|
||||
esac
|
||||
|
||||
$TMUX wait-for $args \; set -g @continued 1 &
|
||||
dead=$!
|
||||
pids="$dead"
|
||||
wait_list "client-$dead" $list_args
|
||||
|
||||
$TMUX wait-for $args &
|
||||
live=$!
|
||||
pids="$dead $live"
|
||||
wait_list "$(printf 'client-%s\nclient-%s' "$dead" "$live")" \
|
||||
$list_args
|
||||
|
||||
kill -"$signal" "$dead" || fail "kill failed"
|
||||
wait "$dead" 2>/dev/null || true
|
||||
pids="$live"
|
||||
wait_list "client-$live" $list_args
|
||||
wait_free "$dead"
|
||||
[ "$($TMUX show -gqv @continued)" = 0 ] ||
|
||||
fail "disconnected client's next command ran"
|
||||
|
||||
case $kind in
|
||||
channel) $TMUX wait-for -S "$name" || fail "signal failed" ;;
|
||||
lock) $TMUX wait-for -U "$name" || fail "unlock failed" ;;
|
||||
event)
|
||||
$TMUX wait-for -E -w "client-$live" "@$name" ||
|
||||
fail "wake event waiter failed"
|
||||
;;
|
||||
esac
|
||||
wait_list "" $list_args
|
||||
wait_free "$live"
|
||||
wait "$live" || fail "surviving waiter failed"
|
||||
pids=
|
||||
if [ "$kind" = lock ]; then
|
||||
$TMUX wait-for -U "$name" || fail "final unlock failed"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# Removing the last waiter must remove its otherwise unused channel, and must
|
||||
# not create a pending signal. Unrelated pending signals must be preserved.
|
||||
$TMUX wait-for -S saved || fail "save signal failed"
|
||||
$TMUX wait-for last &
|
||||
dead=$!
|
||||
pids="$dead"
|
||||
wait_list "client-$dead" last
|
||||
kill -KILL "$dead" || fail "kill last waiter failed"
|
||||
wait "$dead" 2>/dev/null || true
|
||||
pids=
|
||||
wait_list "" last
|
||||
wait_free "$dead"
|
||||
grep -F 'remove empty wait channel last' "$OUT"/tmux-server-*.log \
|
||||
>/dev/null || fail "empty channel was not removed"
|
||||
|
||||
$TMUX wait-for saved \; wait-for last &
|
||||
live=$!
|
||||
pids="$live"
|
||||
wait_list "client-$live" last
|
||||
$TMUX wait-for -S last || fail "signal last failed"
|
||||
wait_free "$live"
|
||||
wait "$live" || fail "pending signal was not preserved"
|
||||
pids=
|
||||
|
||||
# Source-file leaves a cleanup callback behind the blocked command.
|
||||
printf 'wait-for sourced\nset -g @continued 1\n' >"$OUT/source.conf"
|
||||
$TMUX source-file "$OUT/source.conf" &
|
||||
dead=$!
|
||||
pids="$dead"
|
||||
wait_list "client-$dead" sourced
|
||||
kill -KILL "$dead" || fail "kill source-file waiter failed"
|
||||
wait "$dead" 2>/dev/null || true
|
||||
pids=
|
||||
wait_list "" sourced
|
||||
wait_free "$dead"
|
||||
[ "$($TMUX show -gqv @continued)" = 0 ] ||
|
||||
fail "disconnected source-file client's next command ran"
|
||||
|
||||
# Firing an event after cancellation must not call the removed event sink.
|
||||
$TMUX wait-for -E window-renamed &
|
||||
dead=$!
|
||||
pids="$dead"
|
||||
wait_list "client-$dead" -E window-renamed
|
||||
kill -KILL "$dead" || fail "kill event waiter failed"
|
||||
wait "$dead" 2>/dev/null || true
|
||||
pids=
|
||||
wait_list "" -E window-renamed
|
||||
wait_free "$dead"
|
||||
$TMUX rename-window -t test:0 renamed || fail "rename-window failed"
|
||||
$TMUX display-message -p '#{pid}' >/dev/null || fail "server exited"
|
||||
|
||||
exit 0
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: screen-redraw.c,v 1.161 2026/09/22 16:56:07 nicm Exp $ */
|
||||
/* $OpenBSD: screen-redraw.c,v 1.160 2026/09/21 10:22:31 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -1655,7 +1655,7 @@ redraw_draw_pane_prompt(struct redraw_draw_ctx *dctx, struct window_pane *wp)
|
||||
prompt_draw(wp->prompt, &pdd);
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
tty_draw_line(tty, &screen, offset, 0, width, px, cy, NULL);
|
||||
tty_draw_line(tty, &screen, 0, offset, width, px, cy, NULL);
|
||||
screen_free(&screen);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: screen-write.c,v 1.292 2026/09/21 12:14:32 nicm Exp $ */
|
||||
/* $OpenBSD: screen-write.c,v 1.291 2026/09/21 10:22:31 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -833,39 +833,34 @@ 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 border, cx = s->cx, cy = s->cy, i, j, width;
|
||||
u_int cx, cy, i, j, width = menu->width;
|
||||
const char *name;
|
||||
|
||||
cx = s->cx;
|
||||
cy = s->cy;
|
||||
|
||||
memcpy(&default_gc, menu_gc, sizeof default_gc);
|
||||
|
||||
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);
|
||||
}
|
||||
screen_write_box(ctx, menu->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 + border + i, 0);
|
||||
screen_write_hline(ctx, width + 2 + (2 * border), 1, 1,
|
||||
lines, border_gc);
|
||||
screen_write_cursormove(ctx, cx, cy + 1 + i, 0);
|
||||
screen_write_hline(ctx, width + 4, 1, 1, lines,
|
||||
border_gc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (choice >= 0 && i == (u_int)choice && *name != '-')
|
||||
gc = choice_gc;
|
||||
|
||||
screen_write_cursormove(ctx, cx + border, cy + border + i, 0);
|
||||
screen_write_cursormove(ctx, cx + 1, cy + 1 + i, 0);
|
||||
for (j = 0; j < width + 2; j++)
|
||||
screen_write_putc(ctx, gc, ' ');
|
||||
|
||||
screen_write_cursormove(ctx, cx + border + 1, cy + border + i,
|
||||
0);
|
||||
screen_write_cursormove(ctx, cx + 2, cy + 1 + i, 0);
|
||||
if (*name == '-') {
|
||||
default_gc.attr |= GRID_ATTR_DIM;
|
||||
format_draw(ctx, gc, width, name + 1, NULL, 0);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: server-client.c,v 1.514 2026/09/22 06:46:50 nicm Exp $ */
|
||||
/* $OpenBSD: server-client.c,v 1.513 2026/09/21 10:22:31 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -384,9 +384,6 @@ server_client_lost(struct client *c)
|
||||
TAILQ_REMOVE(&clients, c, entry);
|
||||
log_debug("lost client %p", c);
|
||||
|
||||
cmd_wait_for_client_lost(c);
|
||||
cmdq_next(c);
|
||||
|
||||
if (c->flags & CLIENT_ATTACHED) {
|
||||
server_client_attached_lost(c);
|
||||
events_fire_client("client-detached", c);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: server-fn.c,v 1.154 2026/09/21 12:43:36 nicm Exp $ */
|
||||
/* $OpenBSD: server-fn.c,v 1.153 2026/09/10 11:02:18 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -310,8 +310,8 @@ server_link_window(struct session *src, struct winlink *srcwl,
|
||||
}
|
||||
if (killflag) {
|
||||
/*
|
||||
* Can't use session_detach as it won't detach the only
|
||||
* window.
|
||||
* Can't use session_detach as it will destroy session
|
||||
* if this makes it empty.
|
||||
*/
|
||||
events_fire_winlink("window-unlinked", dstwl);
|
||||
dstwl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
|
||||
13
session.c
13
session.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: session.c,v 1.108 2026/09/21 12:43:36 nicm Exp $ */
|
||||
/* $OpenBSD: session.c,v 1.107 2026/08/05 07:35:35 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -336,17 +336,10 @@ session_attach(struct session *s, struct window *w, int idx, char **cause)
|
||||
return (wl);
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach a window from a session. Returns 1 if the window has not been
|
||||
* detached - the caller must destroy the session.
|
||||
*/
|
||||
/* Detach a window from a session. */
|
||||
int
|
||||
session_detach(struct session *s, struct winlink *wl)
|
||||
{
|
||||
if (RB_MIN(winlinks, &s->windows) == wl &&
|
||||
RB_MAX(winlinks, &s->windows) == wl)
|
||||
return (1);
|
||||
|
||||
if (s->curw == wl &&
|
||||
session_last(s) != 0 &&
|
||||
session_previous(s, 0) != 0)
|
||||
@@ -359,6 +352,8 @@ session_detach(struct session *s, struct winlink *wl)
|
||||
|
||||
session_group_synchronize_from(s);
|
||||
|
||||
if (RB_EMPTY(&s->windows))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
6
spawn.c
6
spawn.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: spawn.c,v 1.53 2026/09/21 12:43:36 nicm Exp $ */
|
||||
/* $OpenBSD: spawn.c,v 1.52 2026/08/20 09:19:24 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -166,8 +166,8 @@ spawn_window(struct spawn_context *sc, char **cause)
|
||||
}
|
||||
if (wl != NULL) {
|
||||
/*
|
||||
* Can't use session_detach as it won't detach the only
|
||||
* window.
|
||||
* Can't use session_detach as it will destroy session
|
||||
* if this makes it empty.
|
||||
*/
|
||||
wl->flags &= ~WINLINK_ALERTFLAGS;
|
||||
events_fire_winlink("window-unlinked", wl);
|
||||
|
||||
9
tmux.1
9
tmux.1
@@ -1,4 +1,4 @@
|
||||
.\" $OpenBSD: tmux.1,v 1.1172 2026/09/22 06:58:05 nicm Exp $
|
||||
.\" $OpenBSD: tmux.1,v 1.1171 2026/09/21 10:22:31 nicm Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
.\"
|
||||
@@ -14,7 +14,7 @@
|
||||
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.Dd $Mdocdate: September 22 2026 $
|
||||
.Dd $Mdocdate: September 21 2026 $
|
||||
.Dt TMUX 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -5085,9 +5085,6 @@ The available features are:
|
||||
.Bl -tag -width Ds
|
||||
.It 256
|
||||
Supports 256 colours with the SGR escape sequences.
|
||||
.It appesc
|
||||
Supports application escape key mode, where the Escape key sends a sequence
|
||||
that cannot be mistaken for the start of another key.
|
||||
.It clipboard
|
||||
Allows setting the system clipboard.
|
||||
.It ccolour
|
||||
@@ -8836,8 +8833,6 @@ These are set automatically if the
|
||||
capability is present.
|
||||
.It Em \&Dseks , \&Eneks
|
||||
Disable and enable extended keys.
|
||||
.It Em \&Dsesc , \&Enesc
|
||||
Disable and enable application escape key mode.
|
||||
.It Em \&Dsfcs , \&Enfcs
|
||||
Disable and enable focus reporting.
|
||||
These are set automatically if the
|
||||
|
||||
11
tmux.h
11
tmux.h
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tmux.h,v 1.1447 2026/09/22 14:10:26 nicm Exp $ */
|
||||
/* $OpenBSD: tmux.h,v 1.1442 2026/09/21 10:22:31 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -464,7 +464,6 @@ enum tty_code_code {
|
||||
TTYC_DL1,
|
||||
TTYC_DSBP,
|
||||
TTYC_DSEKS,
|
||||
TTYC_DSESC,
|
||||
TTYC_DSFCS,
|
||||
TTYC_DSMG,
|
||||
TTYC_E3,
|
||||
@@ -475,7 +474,6 @@ enum tty_code_code {
|
||||
TTYC_ENACS,
|
||||
TTYC_ENBP,
|
||||
TTYC_ENEKS,
|
||||
TTYC_ENESC,
|
||||
TTYC_ENFCS,
|
||||
TTYC_ENMG,
|
||||
TTYC_FSL,
|
||||
@@ -1184,7 +1182,6 @@ 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 *);
|
||||
|
||||
@@ -1742,7 +1739,6 @@ struct tty_term {
|
||||
#define TERM_VT100LIKE 0x20
|
||||
#define TERM_SIXEL 0x40
|
||||
#define TERM_INVALIDMS 0x80
|
||||
#define TERM_NOREPLACE 0x100
|
||||
int flags;
|
||||
|
||||
LIST_ENTRY(tty_term) entry;
|
||||
@@ -2988,7 +2984,7 @@ void tty_default_colours(struct grid_cell *, struct window_pane *, u_int *);
|
||||
/* tty-term.c */
|
||||
extern struct tty_terms tty_terms;
|
||||
u_int tty_term_ncodes(void);
|
||||
void tty_term_apply(struct tty_term *, const char *, int, int);
|
||||
void tty_term_apply(struct tty_term *, const char *, int);
|
||||
void tty_term_apply_overrides(struct tty_term *);
|
||||
struct tty_term *tty_term_create(struct tty *, char *, char **, u_int, char **);
|
||||
void tty_term_free(struct tty_term *);
|
||||
@@ -3208,7 +3204,6 @@ void cmdq_print_data(struct cmdq_item *, struct evbuffer *);
|
||||
void printflike(2, 3) cmdq_error(struct cmdq_item *, const char *, ...);
|
||||
|
||||
/* cmd-wait-for.c */
|
||||
void cmd_wait_for_client_lost(struct client *);
|
||||
void cmd_wait_for_flush(void);
|
||||
|
||||
/* client.c */
|
||||
@@ -3809,7 +3804,6 @@ 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 *);
|
||||
@@ -4149,7 +4143,6 @@ 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 *,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tty-draw.c,v 1.17 2026/09/22 06:49:47 nicm Exp $ */
|
||||
/* $OpenBSD: tty-draw.c,v 1.16 2026/09/21 10:22:31 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -218,12 +218,7 @@ tty_draw_line(struct tty *tty, struct screen *s, u_int px, u_int py, u_int nx,
|
||||
}
|
||||
|
||||
/* Did the previous line wrap on to this one? */
|
||||
if (py != 0 &&
|
||||
atx == 0 &&
|
||||
tty->cx >= tty->sx &&
|
||||
tty->cy != UINT_MAX &&
|
||||
tty->cy + 1 == aty &&
|
||||
nx == tty->sx) {
|
||||
if (py != 0 && atx == 0 && tty->cx >= tty->sx && nx == tty->sx) {
|
||||
gl = grid_get_line(gd, gd->hsize + py - 1);
|
||||
if (gl->flags & GRID_LINE_WRAPPED)
|
||||
wrapped = 1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tty-features.c,v 1.45 2026/09/22 14:10:26 nicm Exp $ */
|
||||
/* $OpenBSD: tty-features.c,v 1.43 2026/08/31 12:41:03 kirill Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -189,18 +189,6 @@ static const struct tty_feature tty_feature_focus = {
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports application escape key mode. */
|
||||
static const char *const tty_feature_appesc_capabilities[] = {
|
||||
"Enesc=\\E[?7727h",
|
||||
"Dsesc=\\E[?7727l",
|
||||
NULL
|
||||
};
|
||||
static const struct tty_feature tty_feature_appesc = {
|
||||
"appesc",
|
||||
tty_feature_appesc_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports cursor styles. */
|
||||
static const char *const tty_feature_cstyle_capabilities[] = {
|
||||
"Ss=\\E[%p1%d q",
|
||||
@@ -210,7 +198,7 @@ static const char *const tty_feature_cstyle_capabilities[] = {
|
||||
static const struct tty_feature tty_feature_cstyle = {
|
||||
"cstyle",
|
||||
tty_feature_cstyle_capabilities,
|
||||
TERM_NOREPLACE
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal supports cursor colours. */
|
||||
@@ -390,7 +378,6 @@ static const struct tty_feature tty_feature_utf8 = {
|
||||
/* Available terminal features. */
|
||||
static const struct tty_feature *const tty_features[] = {
|
||||
&tty_feature_256,
|
||||
&tty_feature_appesc,
|
||||
&tty_feature_bpaste,
|
||||
&tty_feature_ccolour,
|
||||
&tty_feature_clipboard,
|
||||
@@ -554,11 +541,11 @@ tty_apply_features(struct tty_term *term)
|
||||
capability = tf->capabilities;
|
||||
while (*capability != NULL) {
|
||||
log_debug("adding capability: %s", *capability);
|
||||
tty_term_apply(term, *capability, 1, tf->flags);
|
||||
tty_term_apply(term, *capability, 1);
|
||||
capability++;
|
||||
}
|
||||
}
|
||||
term->flags |= (tf->flags & ~TERM_NOREPLACE);
|
||||
term->flags |= tf->flags;
|
||||
if (tf == &tty_feature_utf8)
|
||||
c->flags |= CLIENT_UTF8;
|
||||
}
|
||||
@@ -581,7 +568,6 @@ tty_default_features(struct client *c, const char *name, u_int version)
|
||||
"256,RGB,bpaste,clipboard,mouse,strikethrough,title"
|
||||
{ .name = "mintty",
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM ","
|
||||
"appesc,"
|
||||
"ccolour,"
|
||||
"cstyle,"
|
||||
"extkeys,"
|
||||
@@ -637,7 +623,6 @@ tty_default_features(struct client *c, const char *name, u_int version)
|
||||
"extkeys,"
|
||||
"focus,"
|
||||
"hyperlinks,"
|
||||
"margins,"
|
||||
"usstyle"
|
||||
},
|
||||
{ .name = "ghostty",
|
||||
@@ -646,7 +631,6 @@ tty_default_features(struct client *c, const char *name, u_int version)
|
||||
"cstyle,"
|
||||
"extkeys,"
|
||||
"focus,"
|
||||
"margins,"
|
||||
"overline,"
|
||||
"hyperlinks,"
|
||||
"osc7,"
|
||||
@@ -677,7 +661,7 @@ tty_default_features(struct client *c, const char *name, u_int version)
|
||||
"cstyle,"
|
||||
"extkeys,"
|
||||
"focus"
|
||||
},
|
||||
}
|
||||
};
|
||||
u_int i;
|
||||
|
||||
|
||||
12
tty-term.c
12
tty-term.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tty-term.c,v 1.111 2026/09/22 14:10:26 nicm Exp $ */
|
||||
/* $OpenBSD: tty-term.c,v 1.109 2026/08/25 08:37:08 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -90,7 +90,6 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_DL1] = { TTYCODE_STRING, "dl1" },
|
||||
[TTYC_DL] = { TTYCODE_STRING, "dl" },
|
||||
[TTYC_DSEKS] = { TTYCODE_STRING, "Dseks" },
|
||||
[TTYC_DSESC] = { TTYCODE_STRING, "Dsesc" },
|
||||
[TTYC_DSFCS] = { TTYCODE_STRING, "Dsfcs" },
|
||||
[TTYC_DSBP] = { TTYCODE_STRING, "Dsbp" },
|
||||
[TTYC_DSMG] = { TTYCODE_STRING, "Dsmg" },
|
||||
@@ -102,7 +101,6 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_ENACS] = { TTYCODE_STRING, "enacs" },
|
||||
[TTYC_ENBP] = { TTYCODE_STRING, "Enbp" },
|
||||
[TTYC_ENEKS] = { TTYCODE_STRING, "Eneks" },
|
||||
[TTYC_ENESC] = { TTYCODE_STRING, "Enesc" },
|
||||
[TTYC_ENFCS] = { TTYCODE_STRING, "Enfcs" },
|
||||
[TTYC_ENMG] = { TTYCODE_STRING, "Enmg" },
|
||||
[TTYC_FSL] = { TTYCODE_STRING, "fsl" },
|
||||
@@ -364,8 +362,7 @@ tty_term_override_next(const char *s, size_t *offset)
|
||||
}
|
||||
|
||||
void
|
||||
tty_term_apply(struct tty_term *term, const char *capabilities, int quiet,
|
||||
int flags)
|
||||
tty_term_apply(struct tty_term *term, const char *capabilities, int quiet)
|
||||
{
|
||||
const struct tty_term_code_entry *ent;
|
||||
struct tty_code *code;
|
||||
@@ -408,9 +405,6 @@ tty_term_apply(struct tty_term *term, const char *capabilities, int quiet,
|
||||
if (strcmp(s, ent->name) != 0)
|
||||
continue;
|
||||
code = &term->codes[i];
|
||||
if ((flags & TERM_NOREPLACE) &&
|
||||
code->type != TTYCODE_NONE)
|
||||
continue;
|
||||
|
||||
if (remove) {
|
||||
code->type = TTYCODE_NONE;
|
||||
@@ -463,7 +457,7 @@ tty_term_apply_overrides(struct tty_term *term)
|
||||
offset = 0;
|
||||
first = tty_term_override_next(s, &offset);
|
||||
if (first != NULL && fnmatch(first, term->name, 0) == 0)
|
||||
tty_term_apply(term, s + offset, 0, 0);
|
||||
tty_term_apply(term, s + offset, 0);
|
||||
a = options_array_next(a);
|
||||
}
|
||||
|
||||
|
||||
8
tty.c
8
tty.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: tty.c,v 1.482 2026/09/22 06:58:06 nicm Exp $ */
|
||||
/* $OpenBSD: tty.c,v 1.481 2026/09/21 10:22:31 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -502,7 +502,8 @@ tty_stop_tty(struct tty *tty)
|
||||
if (tty_term_has(tty->term, TTYC_DSBP))
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_DSBP));
|
||||
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_DSESC));
|
||||
if (tty->term->flags & TERM_VT100LIKE)
|
||||
tty_raw(tty, "\033[?7727l");
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_DSFCS));
|
||||
tty_raw(tty, tty_term_string(tty->term, TTYC_DSEKS));
|
||||
|
||||
@@ -559,7 +560,8 @@ tty_update_features(struct tty *tty)
|
||||
tty_puts(tty, tty_term_string(tty->term, TTYC_ENEKS));
|
||||
if (options_get_number(global_options, "focus-events"))
|
||||
tty_puts(tty, tty_term_string(tty->term, TTYC_ENFCS));
|
||||
tty_puts(tty, tty_term_string(tty->term, TTYC_ENESC));
|
||||
if (tty->term->flags & TERM_VT100LIKE)
|
||||
tty_puts(tty, "\033[?7727h");
|
||||
|
||||
/*
|
||||
* Features might have changed since the first draw during attach. For
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: window-copy.c,v 1.431 2026/09/21 10:43:37 nicm Exp $ */
|
||||
/* $OpenBSD: window-copy.c,v 1.430 2026/09/21 10:22:31 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) + 1) {
|
||||
while (sy > screen_hsize(src)) {
|
||||
gl = grid_peek_line(src->grid, sy - 1);
|
||||
if (gl == NULL || gl->cellused != 0)
|
||||
break;
|
||||
|
||||
14
window.c
14
window.c
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: window.c,v 1.377 2026/09/21 10:33:16 nicm Exp $ */
|
||||
/* $OpenBSD: window.c,v 1.376 2026/09/21 10:22:31 nicm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||
@@ -2913,15 +2913,3 @@ 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user