Add remain-on-exit failed-key and a -D flag to new-pane to have a modal

pane wait for Escape/C-c. Both to allow better compatibility with
popups.
This commit is contained in:
nicm
2026-09-10 11:02:18 +00:00
committed by tmux update bot
parent b7c5030004
commit d202aa7ac1
6 changed files with 48 additions and 21 deletions

View File

@@ -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>
@@ -41,8 +41,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] "
@@ -220,6 +220,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) {

View File

@@ -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.245 2026/09/10 11:02:18 nicm Exp $ */
/* /*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com> * Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -92,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
@@ -1699,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."
}, },

View File

@@ -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>
@@ -1396,15 +1396,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);
@@ -1761,9 +1765,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) {
@@ -1785,12 +1790,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);

View File

@@ -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>
@@ -383,6 +383,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 */

19
tmux.1
View File

@@ -1,4 +1,4 @@
.\" $OpenBSD: tmux.1,v 1.1168 2026/09/09 07:03:39 nicm Exp $ .\" $OpenBSD: tmux.1,v 1.1169 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>
.\" .\"
@@ -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 10 2026 $
.Dt TMUX 1 .Dt TMUX 1
.Os .Os
.Sh NAME .Sh NAME
@@ -3653,7 +3653,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
@@ -3715,6 +3715,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
@@ -6326,7 +6333,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.
@@ -6336,6 +6343,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.

3
tmux.h
View File

@@ -1,4 +1,4 @@
/* $OpenBSD: tmux.h,v 1.1438 2026/09/09 08:30:05 nicm Exp $ */ /* $OpenBSD: tmux.h,v 1.1439 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>
@@ -1305,6 +1305,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;