mirror of
https://github.com/tmux/tmux.git
synced 2026-09-16 10:11:57 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e880cf63e0 | ||
|
|
325b40e8c4 | ||
|
|
f95363aa83 | ||
|
|
f8fc53b6f8 | ||
|
|
d215280b00 | ||
|
|
d859a0f410 | ||
|
|
10d00cc7cb | ||
|
|
14a01dd337 | ||
|
|
a958883625 | ||
|
|
d202aa7ac1 | ||
|
|
d9a5e82678 | ||
|
|
13c10f672c | ||
|
|
b7c5030004 | ||
|
|
4839123510 | ||
|
|
9b3268a2a0 |
6
CHANGES
6
CHANGES
@@ -33,9 +33,7 @@ CHANGES FROM 3.7c TO 3.8
|
|||||||
line;
|
line;
|
||||||
|
|
||||||
- pane-border-status has top-floating and bottom-floating, and there are new
|
- pane-border-status has top-floating and bottom-floating, and there are new
|
||||||
default bindings under C-b g for common move and resize operations;
|
default bindings under C-b g for common move and resize operations.
|
||||||
|
|
||||||
- floating panes are unzoomed before creation to avoid a crash.
|
|
||||||
|
|
||||||
* Layout strings now use a JSON subset format which includes floating panes.
|
* Layout strings now use a JSON subset format which includes floating panes.
|
||||||
The old format is still accepted; control mode clients receive old layouts
|
The old format is still accepted; control mode clients receive old layouts
|
||||||
@@ -132,6 +130,8 @@ CHANGES FROM 3.7c TO 3.8
|
|||||||
|
|
||||||
* Add capture-pane -I to include the time each line entered history.
|
* Add capture-pane -I to include the time each line entered history.
|
||||||
|
|
||||||
|
* Various memory leak fixes from Heon Jeong.
|
||||||
|
|
||||||
* Add a default C-b T binding to change the current pane title.
|
* Add a default C-b T binding to change the current pane title.
|
||||||
|
|
||||||
* Menus now belong to the window, so appear on all clients.
|
* Menus now belong to the window, so appear on all clients.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: cmd-split-window.c,v 1.150 2026/08/20 09:19:24 nicm Exp $ */
|
/* $OpenBSD: cmd-split-window.c,v 1.151 2026/09/10 11:02:18 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -40,8 +40,8 @@ const struct cmd_entry cmd_new_pane_entry = {
|
|||||||
.name = "new-pane",
|
.name = "new-pane",
|
||||||
.alias = "newp",
|
.alias = "newp",
|
||||||
|
|
||||||
.args = { "AbB:Cc:de:EfF:hIkl:KLMm:Op:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
.args = { "AbB:Cc:Dde:EfF:hIkl:KLMm:Op:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
||||||
.usage = "[-AbCdefhIkKLMOPvWZ] [-B border-lines] "
|
.usage = "[-AbCDefhIkKLMOPvWZ] [-B border-lines] "
|
||||||
"[-c start-directory] [-e environment] "
|
"[-c start-directory] [-e environment] "
|
||||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||||
"[-s style] [-S active-border-style] "
|
"[-s style] [-S active-border-style] "
|
||||||
@@ -219,6 +219,8 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
|||||||
new_wp->flags |= PANE_CAPTUREALLKEYS;
|
new_wp->flags |= PANE_CAPTUREALLKEYS;
|
||||||
if (args_has(args, 'C') && args_has(args, 'O'))
|
if (args_has(args, 'C') && args_has(args, 'O'))
|
||||||
new_wp->flags |= PANE_CLOSEONCLICK;
|
new_wp->flags |= PANE_CLOSEONCLICK;
|
||||||
|
if (args_has(args, 'D') && args_has(args, 'O'))
|
||||||
|
new_wp->flags |= PANE_CLOSEONCANCEL;
|
||||||
|
|
||||||
style = args_get(args, 's');
|
style = args_get(args, 's');
|
||||||
if (style != NULL) {
|
if (style != NULL) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# configure.ac
|
# configure.ac
|
||||||
|
|
||||||
AC_INIT([tmux], next-3.8)
|
AC_INIT([tmux], next-3.9)
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(etc)
|
AC_CONFIG_AUX_DIR(etc)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: layout-custom.c,v 1.40 2026/09/09 07:03:39 nicm Exp $ */
|
/* $OpenBSD: layout-custom.c,v 1.41 2026/09/09 09:01:19 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -28,8 +28,8 @@
|
|||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Layouts can be represented as strings in a JSON format (v2). The legacy
|
* Layouts can be represented as strings in a JSON format (v2). The version 1
|
||||||
* format (v1) will be removed in the future and should no longer be used.
|
* format will be removed in the future and should no longer be used.
|
||||||
*
|
*
|
||||||
* The current (v2) format is JSON. The top level has two keys:
|
* The current (v2) format is JSON. The top level has two keys:
|
||||||
* "V": version number, currently 2
|
* "V": version number, currently 2
|
||||||
@@ -57,6 +57,9 @@
|
|||||||
* "z": z-index, if a floating pane
|
* "z": z-index, if a floating pane
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Maximum nesting depth for version 1 layouts. */
|
||||||
|
#define LAYOUT_V1_MAX_DEPTH 1000
|
||||||
|
|
||||||
/* Layout string. */
|
/* Layout string. */
|
||||||
struct layout_string {
|
struct layout_string {
|
||||||
char *dat;
|
char *dat;
|
||||||
@@ -362,7 +365,7 @@ layout_append_v2(struct layout_cell *lc, struct layout_string *ls)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Append information for a single cell in the legacy (v1) format. */
|
/* Append information for a single cell in the version 1 format. */
|
||||||
static int
|
static int
|
||||||
layout_append_v1(struct layout_cell *lc, struct layout_string *ls)
|
layout_append_v1(struct layout_cell *lc, struct layout_string *ls)
|
||||||
{
|
{
|
||||||
@@ -778,7 +781,7 @@ layout_assign(struct window *w, struct layout_parse_ctx *pctx)
|
|||||||
layout_assign_fallback(w, w->layout_root);
|
layout_assign_fallback(w, w->layout_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct a cell from the legacy (v1) format. */
|
/* Construct a cell from the version 1 format. */
|
||||||
static struct layout_cell *
|
static struct layout_cell *
|
||||||
layout_construct_cell(struct layout_cell *lcparent, const char **layout)
|
layout_construct_cell(struct layout_cell *lcparent, const char **layout)
|
||||||
{
|
{
|
||||||
@@ -827,12 +830,15 @@ layout_construct_cell(struct layout_cell *lcparent, const char **layout)
|
|||||||
return (lc);
|
return (lc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Construct a layout from the legacy (v1) format. */
|
/* Construct a layout from the version 1 format. */
|
||||||
static struct layout_cell *
|
static struct layout_cell *
|
||||||
layout_construct_v1(struct layout_cell *lcparent, const char **layout)
|
layout_construct_v1(struct layout_cell *lcparent, const char **layout, u_int depth)
|
||||||
{
|
{
|
||||||
struct layout_cell *lc, *lcchild;
|
struct layout_cell *lc, *lcchild;
|
||||||
|
|
||||||
|
if (depth > LAYOUT_V1_MAX_DEPTH)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
lc = layout_construct_cell(lcparent, layout);
|
lc = layout_construct_cell(lcparent, layout);
|
||||||
if (lc == NULL)
|
if (lc == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
@@ -855,7 +861,7 @@ layout_construct_v1(struct layout_cell *lcparent, const char **layout)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
(*layout)++;
|
(*layout)++;
|
||||||
lcchild = layout_construct_v1(lc, layout);
|
lcchild = layout_construct_v1(lc, layout, depth + 1);
|
||||||
if (lcchild == NULL)
|
if (lcchild == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
|
TAILQ_INSERT_TAIL(&lc->cells, lcchild, entry);
|
||||||
@@ -1068,7 +1074,8 @@ layout_construct(const char *input, struct layout_parse_ctx *pctx)
|
|||||||
*pctx->cause = xstrdup("invalid layout checksum");
|
*pctx->cause = xstrdup("invalid layout checksum");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
if ((pctx->root = layout_construct_v1(NULL, &input)) == NULL) {
|
pctx->root = layout_construct_v1(NULL, &input, 0);
|
||||||
|
if (pctx->root == NULL) {
|
||||||
*pctx->cause = xstrdup("invalid layout");
|
*pctx->cause = xstrdup("invalid layout");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|||||||
51
layout.c
51
layout.c
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: layout.c,v 1.99 2026/09/09 07:03:39 nicm Exp $ */
|
/* $OpenBSD: layout.c,v 1.100 2026/09/11 08:16:14 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -768,6 +768,49 @@ layout_free(struct window *w, int only_nodes)
|
|||||||
layout_free_cell(w->layout_root, only_nodes);
|
layout_free_cell(w->layout_root, only_nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Move and resize floating panes so they stay inside the window. */
|
||||||
|
static void
|
||||||
|
layout_clamp_floating_panes(struct window *w, u_int sx, u_int sy)
|
||||||
|
{
|
||||||
|
struct window_pane *wp;
|
||||||
|
struct layout_cell *lc;
|
||||||
|
u_int pad, avail, csx, csy;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(wp, &w->z_index, zentry) {
|
||||||
|
lc = wp->layout_cell;
|
||||||
|
if (lc == NULL || (~lc->flags & LAYOUT_CELL_FLOATING))
|
||||||
|
continue;
|
||||||
|
if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE)
|
||||||
|
pad = 0;
|
||||||
|
else
|
||||||
|
pad = 1;
|
||||||
|
|
||||||
|
csx = lc->g.sx;
|
||||||
|
avail = (sx > 2 * pad) ? sx - 2 * pad : 0;
|
||||||
|
if (csx > avail)
|
||||||
|
csx = (avail > PANE_MINIMUM) ? avail : PANE_MINIMUM;
|
||||||
|
csy = lc->g.sy;
|
||||||
|
avail = (sy > 2 * pad) ? sy - 2 * pad : 0;
|
||||||
|
if (csy > avail)
|
||||||
|
csy = (avail > PANE_MINIMUM) ? avail : PANE_MINIMUM;
|
||||||
|
if (csx != lc->g.sx || csy != lc->g.sy)
|
||||||
|
layout_set_size(lc, csx, csy, lc->g.xoff, lc->g.yoff);
|
||||||
|
|
||||||
|
if (lc->g.xoff + lc->g.sx + pad > sx) {
|
||||||
|
if (lc->g.sx + 2 * pad >= sx)
|
||||||
|
lc->g.xoff = pad;
|
||||||
|
else
|
||||||
|
lc->g.xoff = sx - lc->g.sx - pad;
|
||||||
|
}
|
||||||
|
if (lc->g.yoff + lc->g.sy + pad > sy) {
|
||||||
|
if (lc->g.sy + 2 * pad >= sy)
|
||||||
|
lc->g.yoff = pad;
|
||||||
|
else
|
||||||
|
lc->g.yoff = sy - lc->g.sy - pad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Resize the entire layout after window resize. */
|
/* Resize the entire layout after window resize. */
|
||||||
void
|
void
|
||||||
layout_resize(struct window *w, u_int sx, u_int sy)
|
layout_resize(struct window *w, u_int sx, u_int sy)
|
||||||
@@ -788,8 +831,11 @@ layout_resize(struct window *w, u_int sx, u_int sy)
|
|||||||
* out proportionately - this should leave the layout fitting the new
|
* out proportionately - this should leave the layout fitting the new
|
||||||
* window size.
|
* window size.
|
||||||
*/
|
*/
|
||||||
if (lc->type == LAYOUT_WINDOWPANE && (lc->flags & LAYOUT_CELL_FLOATING))
|
if (lc->type == LAYOUT_WINDOWPANE && (lc->flags & LAYOUT_CELL_FLOATING)) {
|
||||||
|
layout_clamp_floating_panes(w, sx, sy);
|
||||||
|
layout_fix_panes(w, NULL);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
xchange = sx - lc->g.sx;
|
xchange = sx - lc->g.sx;
|
||||||
xlimit = layout_resize_check(w, lc, LAYOUT_LEFTRIGHT);
|
xlimit = layout_resize_check(w, lc, LAYOUT_LEFTRIGHT);
|
||||||
if (xchange < 0 && xchange < -xlimit)
|
if (xchange < 0 && xchange < -xlimit)
|
||||||
@@ -819,6 +865,7 @@ layout_resize(struct window *w, u_int sx, u_int sy)
|
|||||||
|
|
||||||
/* Fix cell offsets. */
|
/* Fix cell offsets. */
|
||||||
layout_fix_offsets(w);
|
layout_fix_offsets(w);
|
||||||
|
layout_clamp_floating_panes(w, sx, sy);
|
||||||
layout_fix_panes(w, NULL);
|
layout_fix_panes(w, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: options-table.c,v 1.244 2026/09/01 12:49:49 nicm Exp $ */
|
/* $OpenBSD: options-table.c,v 1.246 2026/09/11 10:17:16 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -76,7 +76,8 @@ static const char *options_table_pane_border_indicators_list[] = {
|
|||||||
"off", "colour", "arrows", "both", NULL
|
"off", "colour", "arrows", "both", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_pane_border_lines_list[] = {
|
static const char *options_table_pane_border_lines_list[] = {
|
||||||
"single", "double", "heavy", "simple", "number", "spaces", "none", NULL
|
"single", "double", "heavy", "simple", "number", "spaces", "none",
|
||||||
|
"rounded", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_popup_border_lines_list[] = {
|
static const char *options_table_popup_border_lines_list[] = {
|
||||||
"single", "double", "heavy", "simple", "rounded", "padded", "none", NULL
|
"single", "double", "heavy", "simple", "rounded", "padded", "none", NULL
|
||||||
@@ -91,7 +92,7 @@ static const char *options_table_window_size_list[] = {
|
|||||||
"largest", "smallest", "manual", "latest", NULL
|
"largest", "smallest", "manual", "latest", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_remain_on_exit_list[] = {
|
static const char *options_table_remain_on_exit_list[] = {
|
||||||
"off", "on", "failed", "key", NULL
|
"off", "on", "failed", "key", "failed-key", NULL
|
||||||
};
|
};
|
||||||
static const char *options_table_destroy_unattached_list[] = {
|
static const char *options_table_destroy_unattached_list[] = {
|
||||||
"off", "on", "keep-last", "keep-group", NULL
|
"off", "on", "keep-last", "keep-group", NULL
|
||||||
@@ -1698,7 +1699,8 @@ const struct options_table_entry options_table[] = {
|
|||||||
.choices = options_table_remain_on_exit_list,
|
.choices = options_table_remain_on_exit_list,
|
||||||
.default_num = 0,
|
.default_num = 0,
|
||||||
.text = "Whether panes should remain ('on'), remain until a key is "
|
.text = "Whether panes should remain ('on'), remain until a key is "
|
||||||
"pressed ('key') or be automatically killed ('off' or "
|
"pressed after any exit ('key') or after a failure "
|
||||||
|
"('failed-key'), or be automatically killed ('off' or "
|
||||||
"'failed') when the program inside exits."
|
"'failed') when the program inside exits."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,11 @@ killw
|
|||||||
EOF
|
EOF
|
||||||
sleep 1
|
sleep 1
|
||||||
$TMUX has || exit 1
|
$TMUX has || exit 1
|
||||||
$TMUX lsp -aF '#{pane_id} #{window_layout}' >$TMP || exit 1
|
# Use a control client to request legacy layouts, keeping only pane lines
|
||||||
cat <<EOF|cmp -s $TMP - || exit 1
|
# from the control protocol output.
|
||||||
|
$TMUX -C lsp -aF '#{pane_id} #{window_layout}' |
|
||||||
|
grep '^%[0-9]' >$TMP || exit 1
|
||||||
|
cat <<EOF|cmp $TMP - || exit 1
|
||||||
%0 f5ab,200x200,0,0[200x50,0,0,0,200x149,0,51,3]
|
%0 f5ab,200x200,0,0[200x50,0,0,0,200x149,0,51,3]
|
||||||
%3 f5ab,200x200,0,0[200x50,0,0,0,200x149,0,51,3]
|
%3 f5ab,200x200,0,0[200x50,0,0,0,200x149,0,51,3]
|
||||||
%2 dcbd,200x200,0,0[200x100,0,0,2,200x99,0,101,4]
|
%2 dcbd,200x200,0,0[200x100,0,0,2,200x99,0,101,4]
|
||||||
|
|||||||
@@ -268,5 +268,149 @@ $TMUX kill-pane -t "$floating" || exit 1
|
|||||||
$TMUX kill-pane -t "$right" || exit 1
|
$TMUX kill-pane -t "$right" || exit 1
|
||||||
$TMUX kill-pane -t "$lower" || exit 1
|
$TMUX kill-pane -t "$lower" || exit 1
|
||||||
|
|
||||||
|
# --- Floating panes clamped when the window shrinks (issue #5581, PR #5582) ---
|
||||||
|
#
|
||||||
|
# layout_resize clamps floating panes back inside the window when it shrinks:
|
||||||
|
# move them and, only if they cannot fit, shrink them (never below
|
||||||
|
# PANE_MINIMUM). A floating cell is the pane's content, so with the default
|
||||||
|
# single-line border the clamp counts 1 cell of border per side, exactly as
|
||||||
|
# layout_floating_args_parse does on creation; with no border it counts 0.
|
||||||
|
# Each case below gets its own window, since resize-window fixes a window at
|
||||||
|
# a manual size for the rest of its life.
|
||||||
|
|
||||||
|
# Case 1: a lone floating pane -- break-pane -W on a window's only pane --
|
||||||
|
# takes the early-return path in layout_resize, added during PR #5582's
|
||||||
|
# review round, since there is no tiled tree to walk.
|
||||||
|
win=$($TMUX new-window -dPF '#{window_id}') ||
|
||||||
|
fail "new-window for lone float failed"
|
||||||
|
|
||||||
|
# -x 20 -y 6 -> pane 18x4; -X 60 -Y 18 -> pane_left 61, pane_top 19: with the
|
||||||
|
# border, the footprint is columns 60-79, rows 18-23, flush with the 80x24
|
||||||
|
# window's right and bottom edges, so the float fits before it is shrunk.
|
||||||
|
$TMUX break-pane -W -s "$win" -x 20 -y 6 -X 60 -Y 18 ||
|
||||||
|
fail "break-pane -W for lone float failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 61
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 19
|
||||||
|
|
||||||
|
# Shrink to 40x16. The float still fits at its own size (18 <= 40-2, 4 <=
|
||||||
|
# 16-2) so only its position moves, flush to the new right/bottom edges:
|
||||||
|
# xoff = 40 - 18 - 1 = 21; yoff = 16 - 4 - 1 = 11.
|
||||||
|
$TMUX resize-window -t "$win" -x 40 -y 16 ||
|
||||||
|
fail "resize-window (lone float) failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 21
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 11
|
||||||
|
|
||||||
|
# Case 5: grow the window back. The clamp must not chase the window back
|
||||||
|
# outward -- it only ever pulls a float in, never restores where it was.
|
||||||
|
$TMUX resize-window -t "$win" -x 80 -y 24 ||
|
||||||
|
fail "resize-window grow (lone float) failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 21
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 11
|
||||||
|
$TMUX kill-window -t "$win" || exit 1
|
||||||
|
|
||||||
|
# Case 2: the same float, but with a tiled sibling surviving alongside it, so
|
||||||
|
# the window's root cell stays tiled and layout_resize takes the normal path
|
||||||
|
# (the clamp call after layout_fix_offsets) instead of the early return
|
||||||
|
# above. Same geometry as case 1, so the same numbers should come out.
|
||||||
|
win=$($TMUX new-window -dPF '#{window_id}') ||
|
||||||
|
fail "new-window for tiled sibling failed"
|
||||||
|
$TMUX split-window -t "$win" 'sleep 100' ||
|
||||||
|
fail "split-window for tiled sibling failed"
|
||||||
|
$TMUX break-pane -W -s "$win" -x 20 -y 6 -X 60 -Y 18 ||
|
||||||
|
fail "break-pane -W for tiled sibling failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 61
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 19
|
||||||
|
|
||||||
|
$TMUX resize-window -t "$win" -x 40 -y 16 ||
|
||||||
|
fail "resize-window (tiled sibling) failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 18
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 4
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 21
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 11
|
||||||
|
$TMUX kill-window -t "$win" || exit 1
|
||||||
|
|
||||||
|
# Case 3: new-pane float, the original repro from issue #5581 and the PR
|
||||||
|
# body -- also the normal path, via the tiled base pane new-window creates.
|
||||||
|
win=$($TMUX new-window -dPF '#{window_id}') ||
|
||||||
|
fail "new-window for new-pane repro failed"
|
||||||
|
$TMUX resize-window -t "$win" -x 120 -y 40 ||
|
||||||
|
fail "resize-window to 120x40 failed"
|
||||||
|
|
||||||
|
# -x 30 -y 10 -> pane 28x8; -X 85 -Y 25 -> pane_left 86, pane_top 26.
|
||||||
|
floating=$($TMUX new-pane -t "$win" -dPF '#{pane_id}' \
|
||||||
|
-x 30 -y 10 -X 85 -Y 25 'sleep 100') ||
|
||||||
|
fail "new-pane for new-pane repro failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 28
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 8
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 86
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 26
|
||||||
|
|
||||||
|
# Shrink to 60x20: xoff = 60 - 28 - 1 = 31; yoff = 20 - 8 - 1 = 11.
|
||||||
|
$TMUX resize-window -t "$win" -x 60 -y 20 ||
|
||||||
|
fail "resize-window (new-pane repro) failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 28
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 8
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 31
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 11
|
||||||
|
$TMUX kill-window -t "$win" || exit 1
|
||||||
|
|
||||||
|
# Case 4: a float that already fits inside the shrunk window is left alone --
|
||||||
|
# assert position and size are both unchanged, not just one of them.
|
||||||
|
win=$($TMUX new-window -dPF '#{window_id}') ||
|
||||||
|
fail "new-window for untouched float failed"
|
||||||
|
|
||||||
|
# -x 20 -y 6 -> pane 18x4; -X 8 -Y 3 -> pane_left 9, pane_top 4 (as at the top
|
||||||
|
# of this file). Footprint columns 8-27, rows 3-8: well inside 60x20 too.
|
||||||
|
floating=$($TMUX new-pane -t "$win" -dPF '#{pane_id}' \
|
||||||
|
-x 20 -y 6 -X 8 -Y 3 'sleep 100') ||
|
||||||
|
fail "new-pane for untouched float failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 18
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 4
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 9
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 4
|
||||||
|
|
||||||
|
$TMUX resize-window -t "$win" -x 60 -y 20 ||
|
||||||
|
fail "resize-window (untouched float) failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_width}')" 18
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_height}')" 4
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_left}')" 9
|
||||||
|
must_equal "$($TMUX display-message -p -t "$floating" '#{pane_top}')" 4
|
||||||
|
$TMUX kill-window -t "$win" || exit 1
|
||||||
|
|
||||||
|
# Case 6: pad = 0, via the pane-border-lines window option set to none. The
|
||||||
|
# border arithmetic differs here (no -2/+1 adjustment either on creation or
|
||||||
|
# in the clamp).
|
||||||
|
win=$($TMUX new-window -dPF '#{window_id}') ||
|
||||||
|
fail "new-window for pad=0 float failed"
|
||||||
|
$TMUX set-option -w -t "$win" pane-border-lines none ||
|
||||||
|
fail "set pane-border-lines none failed"
|
||||||
|
|
||||||
|
# No border: -x 20 -y 6 -> pane 20x6 directly; -X 60 -Y 18 -> pane_left 60,
|
||||||
|
# pane_top 18 directly. Footprint (== content, no border) is columns 60-79,
|
||||||
|
# rows 18-23: flush right/bottom of the 80x24 window, same as case 1.
|
||||||
|
$TMUX break-pane -W -s "$win" -x 20 -y 6 -X 60 -Y 18 ||
|
||||||
|
fail "break-pane -W for pad=0 float failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 20
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 6
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 60
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 18
|
||||||
|
|
||||||
|
# Shrink to 40x16 with pad=0: xoff = 40 - 20 - 0 = 20; yoff = 16 - 6 - 0 = 10.
|
||||||
|
$TMUX resize-window -t "$win" -x 40 -y 16 ||
|
||||||
|
fail "resize-window (pad=0 float) failed"
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_width}')" 20
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_height}')" 6
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_left}')" 20
|
||||||
|
must_equal "$($TMUX display-message -p -t "$win" '#{pane_top}')" 10
|
||||||
|
$TMUX kill-window -t "$win" || exit 1
|
||||||
|
|
||||||
$TMUX kill-server 2>/dev/null
|
$TMUX kill-server 2>/dev/null
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
@@ -337,9 +337,9 @@ $TMUX set -g @modal-prefix no
|
|||||||
$TMUX set -g @modal-root no
|
$TMUX set -g @modal-root no
|
||||||
$TMUX bind -n z set -g @modal-root yes
|
$TMUX bind -n z set -g @modal-root yes
|
||||||
|
|
||||||
modal=$($TMUX new-pane -OKPF '#{pane_id}' -t "$p0" \
|
modal=$($TMUX new-pane -ODKPF '#{pane_id}' -t "$p0" \
|
||||||
-x 20 -y 5 -X 20 -Y 10 'cat') ||
|
-x 20 -y 5 -X 20 -Y 10 'cat') ||
|
||||||
fail "new-pane -OK failed"
|
fail "new-pane -ODK failed"
|
||||||
sleep 1
|
sleep 1
|
||||||
$TMUX2 send-keys -t "$OUTER" C-b x z Enter
|
$TMUX2 send-keys -t "$OUTER" C-b x z Enter
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -356,9 +356,50 @@ new_left=$(fmt "$modal" '#{pane_left}')
|
|||||||
new_top=$(fmt "$modal" '#{pane_top}')
|
new_top=$(fmt "$modal" '#{pane_top}')
|
||||||
[ "$new_left" -gt "$left" ] || [ "$new_top" -gt "$top" ] ||
|
[ "$new_left" -gt "$left" ] || [ "$new_top" -gt "$top" ] ||
|
||||||
fail "key-capturing modal pane did not move"
|
fail "key-capturing modal pane did not move"
|
||||||
|
$TMUX2 send-keys -t "$OUTER" Escape
|
||||||
|
sleep 1
|
||||||
|
must_equal "$(fmt modal:0 '#{window_modal_pane}')" ''
|
||||||
|
|
||||||
|
modal=$($TMUX new-pane -ODKPF '#{pane_id}' -t "$p0" \
|
||||||
|
-x 20 -y 5 -X 20 -Y 10 'trap "" INT; exec cat') ||
|
||||||
|
fail "new-pane -ODK failed"
|
||||||
|
sleep 1
|
||||||
|
$TMUX2 send-keys -t "$OUTER" C-c
|
||||||
|
sleep 1
|
||||||
|
must_equal "$(fmt modal:0 '#{window_modal_pane}')" ''
|
||||||
|
|
||||||
|
# A dead modal does not close on Escape or C-c without -D.
|
||||||
|
modal=$($TMUX new-pane -OPF '#{pane_id}' -t "$p0" \
|
||||||
|
-x 20 -y 5 -X 20 -Y 10 'sleep 1') ||
|
||||||
|
fail "new-pane -O failed"
|
||||||
|
check_ok set-option -p -t "$modal" remain-on-exit on
|
||||||
|
sleep 2
|
||||||
|
must_equal "$(fmt "$modal" '#{pane_dead}:#{pane_modal_flag}')" 1:1
|
||||||
|
$TMUX2 send-keys -t "$OUTER" Escape
|
||||||
|
sleep 1
|
||||||
|
must_equal "$(fmt modal:0 '#{window_modal_pane}')" "$modal"
|
||||||
check_ok kill-pane -t "$modal"
|
check_ok kill-pane -t "$modal"
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
|
# failed-key closes successful panes and retains failed panes until a key.
|
||||||
|
modal=$($TMUX new-pane -OPF '#{pane_id}' -t "$p0" \
|
||||||
|
-x 20 -y 5 -X 20 -Y 10 'sleep 1') ||
|
||||||
|
fail "new-pane -O failed"
|
||||||
|
check_ok set-option -p -t "$modal" remain-on-exit failed-key
|
||||||
|
sleep 2
|
||||||
|
must_equal "$(fmt modal:0 '#{window_modal_pane}')" ''
|
||||||
|
|
||||||
|
modal=$($TMUX new-pane -OPF '#{pane_id}' -t "$p0" \
|
||||||
|
-x 20 -y 5 -X 20 -Y 10 'sleep 1; exit 1') ||
|
||||||
|
fail "new-pane -O failed"
|
||||||
|
check_ok set-option -p -t "$modal" remain-on-exit failed-key
|
||||||
|
sleep 2
|
||||||
|
must_equal "$(fmt "$modal" '#{pane_dead}:#{pane_modal_flag}')" 1:1
|
||||||
|
must_equal "$($TMUX show-options -pv -t "$modal" remain-on-exit)" failed-key
|
||||||
|
$TMUX2 send-keys -t "$OUTER" a
|
||||||
|
sleep 1
|
||||||
|
must_equal "$(fmt modal:0 '#{window_modal_pane}')" ''
|
||||||
|
|
||||||
# A nonmodal floating pane may remain above zoom, and switching between it and
|
# A nonmodal floating pane may remain above zoom, and switching between it and
|
||||||
# the zoomed tiled pane must not unzoom the window.
|
# the zoomed tiled pane must not unzoom the window.
|
||||||
check_ok new-window -d -t modal: -n float-over-zoom 'cat'
|
check_ok new-window -d -t modal: -n float-over-zoom 'cat'
|
||||||
|
|||||||
@@ -86,6 +86,11 @@ check_value "-gv status-keys" "vi"
|
|||||||
check_fail "unknown value: bogus" set -g status-keys bogus
|
check_fail "unknown value: bogus" set -g status-keys bogus
|
||||||
check_value "-gv status-keys" "vi"
|
check_value "-gv status-keys" "vi"
|
||||||
|
|
||||||
|
# pane-border-lines accepts rounded as a pane border style.
|
||||||
|
check_ok set -gw pane-border-lines rounded
|
||||||
|
check_value "-gwv pane-border-lines" "rounded"
|
||||||
|
check_ok set -gw pane-border-lines single
|
||||||
|
|
||||||
# --- flag options ---------------------------------------------------------
|
# --- flag options ---------------------------------------------------------
|
||||||
#
|
#
|
||||||
# focus-events is an on/off flag. Setting with no value toggles it; explicit
|
# focus-events is an on/off flag. Setting with no value toggles it; explicit
|
||||||
|
|||||||
@@ -104,6 +104,25 @@ assert_alive()
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Compare layout geometry and pane ordering, ignoring the active pane and
|
||||||
|
# last-pane history in the JSON layout. Selection is checked separately.
|
||||||
|
pane_layout()
|
||||||
|
{
|
||||||
|
$TMUX display-message -p -t "$1" '#{window_layout}' |
|
||||||
|
sed 's/,"a":true//g; s/,"l":[0-9][0-9]*//g'
|
||||||
|
}
|
||||||
|
|
||||||
|
check_layout()
|
||||||
|
{
|
||||||
|
out=$(pane_layout "$1")
|
||||||
|
if [ "$out" != "$2" ]; then
|
||||||
|
echo "Layout for '$1' wrong."
|
||||||
|
echo "Expected: '$2'"
|
||||||
|
echo "But got: '$out'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# split-window geometry.
|
# split-window geometry.
|
||||||
|
|
||||||
@@ -309,12 +328,12 @@ check_ok kill-pane -t "$p6"
|
|||||||
|
|
||||||
# Zoom and unzoom preserve the exact tiled layout. Selecting another pane
|
# Zoom and unzoom preserve the exact tiled layout. Selecting another pane
|
||||||
# without -Z unzooms, while -Z transfers zoom to the selected pane.
|
# without -Z unzooms, while -Z transfers zoom to the selected pane.
|
||||||
layout=$($TMUX display-message -p -t P:0 '#{window_layout}')
|
layout=$(pane_layout P:0)
|
||||||
check_ok select-pane -t "$p0"
|
check_ok select-pane -t "$p0"
|
||||||
check_ok resize-pane -Z -t "$p0"
|
check_ok resize-pane -Z -t "$p0"
|
||||||
check_ok select-pane -t "$p2"
|
check_ok select-pane -t "$p2"
|
||||||
check_fmt "$p2" '#{window_zoomed_flag}:#{pane_active}' '0:1'
|
check_fmt "$p2" '#{window_zoomed_flag}:#{pane_active}' '0:1'
|
||||||
check_fmt P:0 '#{window_layout}' "$layout"
|
check_layout P:0 "$layout"
|
||||||
|
|
||||||
check_ok select-pane -t "$p0"
|
check_ok select-pane -t "$p0"
|
||||||
check_ok resize-pane -Z -t "$p0"
|
check_ok resize-pane -Z -t "$p0"
|
||||||
@@ -322,7 +341,7 @@ check_ok select-pane -Z -t "$p2"
|
|||||||
check_fmt "$p2" '#{window_zoomed_flag}:#{pane_zoomed_flag}:#{pane_active}' \
|
check_fmt "$p2" '#{window_zoomed_flag}:#{pane_zoomed_flag}:#{pane_active}' \
|
||||||
'1:1:1'
|
'1:1:1'
|
||||||
check_ok resize-pane -Z -t "$p2"
|
check_ok resize-pane -Z -t "$p2"
|
||||||
check_fmt P:0 '#{window_layout}' "$layout"
|
check_layout P:0 "$layout"
|
||||||
|
|
||||||
# Directional selection temporarily restores the full layout to find its
|
# Directional selection temporarily restores the full layout to find its
|
||||||
# neighbour, then follows the same unzoom or -Z transfer rules.
|
# neighbour, then follows the same unzoom or -Z transfer rules.
|
||||||
@@ -340,7 +359,7 @@ check_ok select-pane -D -Z -t "$p0"
|
|||||||
check_fmt "$p2" '#{window_zoomed_flag}:#{pane_zoomed_flag}:#{pane_active}' \
|
check_fmt "$p2" '#{window_zoomed_flag}:#{pane_zoomed_flag}:#{pane_active}' \
|
||||||
'1:1:1'
|
'1:1:1'
|
||||||
check_ok resize-pane -Z -t "$p2"
|
check_ok resize-pane -Z -t "$p2"
|
||||||
check_fmt P:0 '#{window_layout}' "$layout"
|
check_layout P:0 "$layout"
|
||||||
|
|
||||||
# The last-pane path has separate zoom handling, both with and without -Z.
|
# The last-pane path has separate zoom handling, both with and without -Z.
|
||||||
check_ok select-pane -t "$p0"
|
check_ok select-pane -t "$p0"
|
||||||
@@ -357,7 +376,7 @@ check_ok select-pane -l -Z -t P:0
|
|||||||
check_fmt "$p0" '#{window_zoomed_flag}:#{pane_zoomed_flag}:#{pane_active}' \
|
check_fmt "$p0" '#{window_zoomed_flag}:#{pane_zoomed_flag}:#{pane_active}' \
|
||||||
'1:1:1'
|
'1:1:1'
|
||||||
check_ok resize-pane -Z -t "$p0"
|
check_ok resize-pane -Z -t "$p0"
|
||||||
check_fmt P:0 '#{window_layout}' "$layout"
|
check_layout P:0 "$layout"
|
||||||
|
|
||||||
# Killing either a hidden ordinary pane or the zoom target unzooms.
|
# Killing either a hidden ordinary pane or the zoom target unzooms.
|
||||||
check_ok new-window -d -t P:12 -n zoom-kill 'cat'
|
check_ok new-window -d -t P:12 -n zoom-kill 'cat'
|
||||||
|
|||||||
@@ -107,6 +107,12 @@ $TMUX2 new-pane -x28 -y8 -X4 -Y1 -B double \
|
|||||||
"sh -c 'printf FLOAT; exec sleep 100'" || exit 1
|
"sh -c 'printf FLOAT; exec sleep 100'" || exit 1
|
||||||
compare floating-border-double
|
compare floating-border-double
|
||||||
|
|
||||||
|
# Larger floating pane with rounded border lines.
|
||||||
|
new_scene 40 12
|
||||||
|
$TMUX2 new-pane -x28 -y8 -X4 -Y1 -B rounded \
|
||||||
|
"sh -c 'printf FLOAT; exec sleep 100'" || exit 1
|
||||||
|
compare floating-border-rounded
|
||||||
|
|
||||||
# Floating pane with no border lines: redraw_mark_pane_borders returns early so
|
# Floating pane with no border lines: redraw_mark_pane_borders returns early so
|
||||||
# the float has no border at all, only its (clipped) content over the base pane.
|
# the float has no border at all, only its (clipped) content over the base pane.
|
||||||
new_scene 40 12
|
new_scene 40 12
|
||||||
|
|||||||
12
regress/screen-redraw-results/floating-border-rounded.result
Normal file
12
regress/screen-redraw-results/floating-border-rounded.result
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
base
|
||||||
|
╭──────────────────────────╮
|
||||||
|
│FLOAT │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
╰──────────────────────────╯
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: server-client.c,v 1.511 2026/09/08 10:20:08 nicm Exp $ */
|
/* $OpenBSD: server-client.c,v 1.512 2026/09/10 11:02:18 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -1391,15 +1391,19 @@ server_client_repeat_time(struct client *c, struct key_binding *bd)
|
|||||||
return (repeat);
|
return (repeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle a key press on a dead pane waiting for a key. */
|
/* Handle a key press which closes a dead pane. */
|
||||||
static int
|
static int
|
||||||
server_client_handle_dead_key(struct window_pane *wp, key_code key)
|
server_client_handle_dead_key(struct window_pane *wp, key_code key)
|
||||||
{
|
{
|
||||||
|
int remain_on_exit;
|
||||||
|
|
||||||
if (wp == NULL ||
|
if (wp == NULL ||
|
||||||
(~wp->flags & PANE_EXITED) ||
|
(~wp->flags & PANE_EXITED) ||
|
||||||
KEYC_IS_MOUSE(key) ||
|
KEYC_IS_MOUSE(key) ||
|
||||||
KEYC_IS_PASTE(key) ||
|
KEYC_IS_PASTE(key))
|
||||||
options_get_number(wp->options, "remain-on-exit") != 3)
|
return (0);
|
||||||
|
remain_on_exit = options_get_number(wp->options, "remain-on-exit");
|
||||||
|
if (remain_on_exit != 3 && remain_on_exit != 4)
|
||||||
return (0);
|
return (0);
|
||||||
options_set_number(wp->options, "remain-on-exit", 0);
|
options_set_number(wp->options, "remain-on-exit", 0);
|
||||||
server_destroy_pane(wp, 0);
|
server_destroy_pane(wp, 0);
|
||||||
@@ -1756,9 +1760,10 @@ server_client_handle_key0(struct client *c, struct key_event *event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Key presses in overlay mode, for panes capturing all keys and in the
|
* Key presses in overlay mode, dead panes waiting for a key, modal cancel
|
||||||
* command prompt are a special case. The queue might be blocked so they
|
* keys, panes capturing all keys and the command prompt are special cases.
|
||||||
* need to be processed immediately rather than queued.
|
* The queue might be blocked so they need to be processed immediately
|
||||||
|
* rather than queued.
|
||||||
*/
|
*/
|
||||||
if (~c->flags & CLIENT_READONLY) {
|
if (~c->flags & CLIENT_READONLY) {
|
||||||
if (c->message_string != NULL) {
|
if (c->message_string != NULL) {
|
||||||
@@ -1780,12 +1785,18 @@ server_client_handle_key0(struct client *c, struct key_event *event,
|
|||||||
server_client_clear_overlay(c);
|
server_client_clear_overlay(c);
|
||||||
|
|
||||||
wp = s->curw->window->active;
|
wp = s->curw->window->active;
|
||||||
|
if (server_client_handle_dead_key(wp, event->key))
|
||||||
|
return (0);
|
||||||
|
if (wp != NULL && wp == wp->window->modal &&
|
||||||
|
(wp->flags & PANE_CLOSEONCANCEL) &&
|
||||||
|
(event->key == '\033' || event->key == ('c'|KEYC_CTRL))) {
|
||||||
|
server_kill_pane(wp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
if (wp != NULL &&
|
if (wp != NULL &&
|
||||||
(wp->flags & PANE_CAPTUREALLKEYS) &&
|
(wp->flags & PANE_CAPTUREALLKEYS) &&
|
||||||
TAILQ_EMPTY(&wp->modes) &&
|
TAILQ_EMPTY(&wp->modes) &&
|
||||||
!KEYC_IS_MOUSE(event->key)) {
|
!KEYC_IS_MOUSE(event->key)) {
|
||||||
if (server_client_handle_dead_key(wp, event->key))
|
|
||||||
return (0);
|
|
||||||
if (~wp->flags & PANE_EXITED) {
|
if (~wp->flags & PANE_EXITED) {
|
||||||
window_pane_key(wp, c, s, s->curw, event->key,
|
window_pane_key(wp, c, s, s->curw, event->key,
|
||||||
&event->m);
|
&event->m);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: server-fn.c,v 1.152 2026/09/03 19:12: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>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -386,6 +386,7 @@ server_destroy_pane(struct window_pane *wp, int notify)
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
case 4:
|
||||||
if (WIFEXITED(wp->status) && WEXITSTATUS(wp->status) == 0)
|
if (WIFEXITED(wp->status) && WEXITSTATUS(wp->status) == 0)
|
||||||
break;
|
break;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
|||||||
21
tmux.1
21
tmux.1
@@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: tmux.1,v 1.1168 2026/09/09 07:03:39 nicm Exp $
|
.\" $OpenBSD: tmux.1,v 1.1170 2026/09/11 10:17:16 nicm Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
.\"
|
.\"
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||||
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: September 9 2026 $
|
.Dd $Mdocdate: September 11 2026 $
|
||||||
.Dt TMUX 1
|
.Dt TMUX 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@@ -3655,7 +3655,7 @@ but a different format may be specified with
|
|||||||
.Fl F .
|
.Fl F .
|
||||||
.Tg newp
|
.Tg newp
|
||||||
.It Xo Ic new\-pane
|
.It Xo Ic new\-pane
|
||||||
.Op Fl AbCdefhIkKLMOPvWZ
|
.Op Fl AbCDefhIkKLMOPvWZ
|
||||||
.Op Fl B Ar border\-lines
|
.Op Fl B Ar border\-lines
|
||||||
.Op Fl c Ar start\-directory
|
.Op Fl c Ar start\-directory
|
||||||
.Op Fl e Ar environment
|
.Op Fl e Ar environment
|
||||||
@@ -3717,6 +3717,13 @@ all keys, including the prefix key, are passed directly to the modal pane.
|
|||||||
With
|
With
|
||||||
.Fl C ,
|
.Fl C ,
|
||||||
the modal pane is closed when the mouse is clicked outside it.
|
the modal pane is closed when the mouse is clicked outside it.
|
||||||
|
With
|
||||||
|
.Fl D ,
|
||||||
|
the modal pane is closed when
|
||||||
|
.Ql Escape
|
||||||
|
or
|
||||||
|
.Ql C-c
|
||||||
|
is pressed.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Fl L
|
.Fl L
|
||||||
@@ -5973,6 +5980,8 @@ single lines using ACS or UTF\-8 characters
|
|||||||
double lines using UTF\-8 characters
|
double lines using UTF\-8 characters
|
||||||
.It heavy
|
.It heavy
|
||||||
heavy lines using UTF\-8 characters
|
heavy lines using UTF\-8 characters
|
||||||
|
.It rounded
|
||||||
|
single lines with rounded corners using UTF\-8 characters
|
||||||
.It simple
|
.It simple
|
||||||
simple ASCII characters
|
simple ASCII characters
|
||||||
.It number
|
.It number
|
||||||
@@ -6328,7 +6337,7 @@ uses when the colour with that index is requested.
|
|||||||
The index may be from zero to 255.
|
The index may be from zero to 255.
|
||||||
.Pp
|
.Pp
|
||||||
.It Xo Ic remain\-on\-exit
|
.It Xo Ic remain\-on\-exit
|
||||||
.Op Ic on | off | failed | key
|
.Op Ic on | off | failed | key | failed\-key
|
||||||
.Xc
|
.Xc
|
||||||
A pane with this flag set is not destroyed when the program running in it
|
A pane with this flag set is not destroyed when the program running in it
|
||||||
exits.
|
exits.
|
||||||
@@ -6338,6 +6347,10 @@ then only when the program exit status is not zero.
|
|||||||
If set to
|
If set to
|
||||||
.Ic key ,
|
.Ic key ,
|
||||||
the pane stays open and closes when a key is pressed.
|
the pane stays open and closes when a key is pressed.
|
||||||
|
If set to
|
||||||
|
.Ic failed\-key ,
|
||||||
|
the pane stays open and closes when a key is pressed only if the program exit
|
||||||
|
status is not zero.
|
||||||
The pane may be reactivated with the
|
The pane may be reactivated with the
|
||||||
.Ic respawn\-pane
|
.Ic respawn\-pane
|
||||||
command.
|
command.
|
||||||
|
|||||||
6
tmux.h
6
tmux.h
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tmux.h,v 1.1438 2026/09/09 08:30:05 nicm Exp $ */
|
/* $OpenBSD: tmux.h,v 1.1440 2026/09/11 10:17:16 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -1150,7 +1150,8 @@ enum pane_lines {
|
|||||||
PANE_LINES_SIMPLE,
|
PANE_LINES_SIMPLE,
|
||||||
PANE_LINES_NUMBER,
|
PANE_LINES_NUMBER,
|
||||||
PANE_LINES_SPACES,
|
PANE_LINES_SPACES,
|
||||||
PANE_LINES_NONE
|
PANE_LINES_NONE,
|
||||||
|
PANE_LINES_ROUNDED
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Pane border indicator option. */
|
/* Pane border indicator option. */
|
||||||
@@ -1339,6 +1340,7 @@ struct window_pane {
|
|||||||
#define PANE_CLOSEONCLICK 0x80000
|
#define PANE_CLOSEONCLICK 0x80000
|
||||||
#define PANE_CAPTUREALLKEYS 0x100000
|
#define PANE_CAPTUREALLKEYS 0x100000
|
||||||
#define PANE_FLOATOVERZOOM 0x200000
|
#define PANE_FLOATOVERZOOM 0x200000
|
||||||
|
#define PANE_CLOSEONCANCEL 0x400000
|
||||||
|
|
||||||
bitstr_t *sync_dirty;
|
bitstr_t *sync_dirty;
|
||||||
u_int sync_dirty_size;
|
u_int sync_dirty_size;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: window-border.c,v 1.3 2026/07/23 09:38:27 nicm Exp $ */
|
/* $OpenBSD: window-border.c,v 1.4 2026/09/11 10:17:16 nicm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
* Copyright (c) 2026 Nicholas Marriott <nicholas.marriott@gmail.com>
|
||||||
@@ -120,6 +120,10 @@ window_get_border_cell(struct window_pane *wp, enum pane_lines pane_lines,
|
|||||||
gc->attr &= ~GRID_ATTR_CHARSET;
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
|
utf8_copy(&gc->data, tty_acs_heavy_borders(cell_type));
|
||||||
break;
|
break;
|
||||||
|
case PANE_LINES_ROUNDED:
|
||||||
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
|
utf8_copy(&gc->data, tty_acs_rounded_borders(cell_type));
|
||||||
|
break;
|
||||||
case PANE_LINES_SIMPLE:
|
case PANE_LINES_SIMPLE:
|
||||||
gc->attr &= ~GRID_ATTR_CHARSET;
|
gc->attr &= ~GRID_ATTR_CHARSET;
|
||||||
utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
|
utf8_set(&gc->data, SIMPLE_BORDERS[cell_type]);
|
||||||
|
|||||||
Reference in New Issue
Block a user