From 930d157de30352a265fd289fb2f39469c165d6fc Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 2 Aug 2022 11:09:26 +0000 Subject: [PATCH] Add a third state "all" to allow-passthrough to work even in invisible panes, from Sergei Grechanik in GitHub issue 3274. --- usr.bin/tmux/input.c | 13 +++++++--- usr.bin/tmux/options-table.c | 12 ++++++--- usr.bin/tmux/screen-write.c | 6 +++-- usr.bin/tmux/tmux.1 | 10 ++++++-- usr.bin/tmux/tmux.h | 48 +++++++++++++++++++++--------------- usr.bin/tmux/tty.c | 23 +++++++++++------ 6 files changed, 73 insertions(+), 39 deletions(-) diff --git a/usr.bin/tmux/input.c b/usr.bin/tmux/input.c index 147a3e68e59..447f461c40d 100644 --- a/usr.bin/tmux/input.c +++ b/usr.bin/tmux/input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: input.c,v 1.206 2022/06/30 09:55:53 nicm Exp $ */ +/* $OpenBSD: input.c,v 1.207 2022/08/02 11:09:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -2242,22 +2242,27 @@ static int input_dcs_dispatch(struct input_ctx *ictx) { struct window_pane *wp = ictx->wp; + struct options *oo = wp->options; struct screen_write_ctx *sctx = &ictx->ctx; u_char *buf = ictx->input_buf; size_t len = ictx->input_len; const char prefix[] = "tmux;"; const u_int prefixlen = (sizeof prefix) - 1; + long long allow_passthrough = 0; if (wp == NULL) return (0); if (ictx->flags & INPUT_DISCARD) return (0); - if (!options_get_number(ictx->wp->options, "allow-passthrough")) + allow_passthrough = options_get_number(oo, "allow-passthrough"); + if (!allow_passthrough) return (0); log_debug("%s: \"%s\"", __func__, buf); - if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) - screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen); + if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0) { + screen_write_rawstring(sctx, buf + prefixlen, len - prefixlen, + allow_passthrough == 2); + } return (0); } diff --git a/usr.bin/tmux/options-table.c b/usr.bin/tmux/options-table.c index 99820aaab6d..d16eed85050 100644 --- a/usr.bin/tmux/options-table.c +++ b/usr.bin/tmux/options-table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options-table.c,v 1.163 2022/06/14 07:29:00 nicm Exp $ */ +/* $OpenBSD: options-table.c,v 1.164 2022/08/02 11:09:26 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -88,6 +88,9 @@ static const char *options_table_detach_on_destroy_list[] = { static const char *options_table_extended_keys_list[] = { "off", "on", "always", NULL }; +static const char *options_table_allow_passthrough_list[] = { + "off", "on", "all", NULL +}; /* Status line format. */ #define OPTIONS_TABLE_STATUS_FORMAT1 \ @@ -804,11 +807,14 @@ const struct options_table_entry options_table[] = { }, { .name = "allow-passthrough", - .type = OPTIONS_TABLE_FLAG, + .type = OPTIONS_TABLE_CHOICE, .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE, + .choices = options_table_allow_passthrough_list, .default_num = 0, .text = "Whether applications are allowed to use the escape sequence " - "to bypass tmux." + "to bypass tmux. Can be 'off' (disallowed), 'on' (allowed " + "if the pane is visible), or 'all' (allowed even if the pane " + "is invisible)." }, { .name = "allow-rename", diff --git a/usr.bin/tmux/screen-write.c b/usr.bin/tmux/screen-write.c index 814a1bff4d7..5fcb8e00af7 100644 --- a/usr.bin/tmux/screen-write.c +++ b/usr.bin/tmux/screen-write.c @@ -1,4 +1,4 @@ -/* $OpenBSD: screen-write.c,v 1.208 2022/06/09 09:12:55 nicm Exp $ */ +/* $OpenBSD: screen-write.c,v 1.209 2022/08/02 11:09:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -2100,13 +2100,15 @@ screen_write_setselection(struct screen_write_ctx *ctx, const char *flags, /* Write unmodified string. */ void -screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len) +screen_write_rawstring(struct screen_write_ctx *ctx, u_char *str, u_int len, + int allow_invisible_panes) { struct tty_ctx ttyctx; screen_write_initctx(ctx, &ttyctx, 0); ttyctx.ptr = str; ttyctx.num = len; + ttyctx.allow_invisible_panes = allow_invisible_panes; tty_write(tty_cmd_rawstring, &ttyctx); } diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index dcd1b10feca..c9f28d3157c 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.896 2022/08/02 08:57:01 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.897 2022/08/02 11:09:26 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -4461,11 +4461,17 @@ Available pane options are: .Pp .Bl -tag -width Ds -compact .It Xo Ic allow-passthrough -.Op Ic on | off +.Op Ic on | off | all .Xc Allow programs in the pane to bypass .Nm using a terminal escape sequence (\eePtmux;...\ee\e\e). +If set to +.Ic on , +passthrough sequences will be allowed only if the pane is visible. +If set to +.Ic all , +they will be allowed even if the pane is invisible. .Pp .It Xo Ic allow-rename .Op Ic on | off diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 27861fcd36e..cabf7e45f3a 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1178 2022/07/06 08:31:59 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1179 2022/08/02 11:09:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1431,38 +1431,45 @@ struct tty_ctx { void *ptr; void *ptr2; + /* + * Whether this command should be sent even when the pane is not + * visible (used for a passthrough sequence when allow-passthrough is + * "all"). + */ + int allow_invisible_panes; + /* * Cursor and region position before the screen was updated - this is * where the command should be applied; the values in the screen have * already been updated. */ - u_int ocx; - u_int ocy; + u_int ocx; + u_int ocy; - u_int orupper; - u_int orlower; + u_int orupper; + u_int orlower; /* Target region (usually pane) offset and size. */ - u_int xoff; - u_int yoff; - u_int rxoff; - u_int ryoff; - u_int sx; - u_int sy; + u_int xoff; + u_int yoff; + u_int rxoff; + u_int ryoff; + u_int sx; + u_int sy; /* The background colour used for clearing (erasing). */ - u_int bg; + u_int bg; /* The default colours and palette. */ - struct grid_cell defaults; - struct colour_palette *palette; + struct grid_cell defaults; + struct colour_palette *palette; /* Containing region (usually window) offset and size. */ - int bigger; - u_int wox; - u_int woy; - u_int wsx; - u_int wsy; + int bigger; + u_int wox; + u_int woy; + u_int wsx; + u_int wsy; }; /* Saved message entry. */ @@ -2889,7 +2896,8 @@ void screen_write_collect_add(struct screen_write_ctx *, void screen_write_cell(struct screen_write_ctx *, const struct grid_cell *); void screen_write_setselection(struct screen_write_ctx *, const char *, u_char *, u_int); -void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int); +void screen_write_rawstring(struct screen_write_ctx *, u_char *, u_int, + int); void screen_write_alternateon(struct screen_write_ctx *, struct grid_cell *, int); void screen_write_alternateoff(struct screen_write_ctx *, diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index e029c9c2710..4077b9ad528 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.422 2022/07/06 07:36:36 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.423 2022/08/02 11:09:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -1626,13 +1626,20 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *), if (ctx->set_client_cb == NULL) return; TAILQ_FOREACH(c, &clients, entry) { - if (!tty_client_ready(c)) - continue; - state = ctx->set_client_cb(ctx, c); - if (state == -1) - break; - if (state == 0) - continue; + if (ctx->allow_invisible_panes) { + if (c->session == NULL || + c->tty.term == NULL || + c->flags & CLIENT_SUSPENDED) + continue; + } else { + if (!tty_client_ready(c)) + continue; + state = ctx->set_client_cb(ctx, c); + if (state == -1) + break; + if (state == 0) + continue; + } cmdfn(&c->tty, ctx); } } -- 2.20.1