diff --git a/options-table.c b/options-table.c index 8fcb4d0b9..c3b7d0fc6 100644 --- a/options-table.c +++ b/options-table.c @@ -1,4 +1,4 @@ -/* $OpenBSD: options-table.c,v 1.242 2026/07/27 08:03:01 nicm Exp $ */ +/* $OpenBSD: options-table.c,v 1.243 2026/08/25 08:37:08 nicm Exp $ */ /* * Copyright (c) 2011 Nicholas Marriott @@ -305,6 +305,16 @@ const struct options_table_entry options_table[] = { "When this is reached, the oldest buffer is deleted." }, + { .name = "clear-on-attach", + .type = OPTIONS_TABLE_FLAG, + .scope = OPTIONS_TABLE_SERVER, + .default_num = 1, + .text = "Whether to use the alternate screen and clear it when " + "a client is attached. When disabled, tmux does not " + "enter the alternate screen on attach so terminal " + "content before tmux remains in scrollback." + }, + { .name = "command-alias", .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_SERVER, diff --git a/tmux.1 b/tmux.1 index 1e641602e..7bfc5a352 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.1158 2026/08/20 09:19:24 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.1159 2026/08/25 08:37:08 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott .\" @@ -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: August 20 2026 $ +.Dd $Mdocdate: August 25 2026 $ .Dt TMUX 1 .Os .Sh NAME @@ -4754,6 +4754,15 @@ for backspace. Set the number of buffers; as new buffers are added to the top of the stack, old ones are removed from the bottom if necessary to maintain this maximum length. +.It Xo Ic clear\-on\-attach +.Op Ic on | off +.Xc +When enabled (the default), the client terminal switches to the alternate +screen and clears it when a client is attached. +When disabled, +.Nm +does not enter the alternate screen; instead the existing terminal content is +scrolled into the scrollback buffer so it remains accessible. .It Xo Ic command\-alias[] .Ar name=value .Xc diff --git a/tmux.h b/tmux.h index 4a758c497..0bc368417 100644 --- a/tmux.h +++ b/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1430 2026/08/24 21:17:19 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1431 2026/08/25 08:37:08 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -483,6 +483,7 @@ enum tty_code_code { TTYC_ICH1, TTYC_IL, TTYC_IL1, + TTYC_IND, TTYC_INDN, TTYC_INVIS, TTYC_KCBT, diff --git a/tty-term.c b/tty-term.c index 8e0248e84..6b149fcee 100644 --- a/tty-term.c +++ b/tty-term.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-term.c,v 1.108 2026/08/17 14:47:41 nicm Exp $ */ +/* $OpenBSD: tty-term.c,v 1.109 2026/08/25 08:37:08 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -111,6 +111,7 @@ static const struct tty_term_code_entry tty_term_codes[] = { [TTYC_ICH] = { TTYCODE_STRING, "ich" }, [TTYC_IL1] = { TTYCODE_STRING, "il1" }, [TTYC_IL] = { TTYCODE_STRING, "il" }, + [TTYC_IND] = { TTYCODE_STRING, "ind" }, [TTYC_INDN] = { TTYCODE_STRING, "indn" }, [TTYC_INVIS] = { TTYCODE_STRING, "invis" }, [TTYC_KCBT] = { TTYCODE_STRING, "kcbt" }, diff --git a/tty.c b/tty.c index e8a60c68d..9bac687eb 100644 --- a/tty.c +++ b/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.479 2026/08/18 09:01:20 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.480 2026/08/25 08:37:08 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -338,6 +338,7 @@ tty_start_tty(struct tty *tty) { struct client *c = tty->client; struct termios tio; + u_int i; setblocking(c->fd, 0); event_add(&tty->event_in, NULL); @@ -353,10 +354,21 @@ tty_start_tty(struct tty *tty) if (tcsetattr(c->fd, TCSANOW, &tio) == 0) tcflush(c->fd, TCOFLUSH); - tty_putcode(tty, TTYC_SMCUP); - + if (options_get_number(global_options, "clear-on-attach")) { + tty_putcode(tty, TTYC_SMCUP); + tty_putcode(tty, TTYC_CLEAR); + } else { + tty_putcode_ii(tty, TTYC_CSR, 0, tty->sy - 1); + tty_putcode_ii(tty, TTYC_CUP, 0, tty->sy - 1); + if (tty_term_has(tty->term, TTYC_INDN)) + tty_putcode_i(tty, TTYC_INDN, tty->sy + 1); + else if (tty_term_has(tty->term, TTYC_IND)) { + for (i = 0; i < tty->sy + 1; i++) + tty_putcode(tty, TTYC_IND); + } else + tty_putcode(tty, TTYC_CLEAR); + } tty_putcode(tty, TTYC_SMKX); - tty_putcode(tty, TTYC_CLEAR); if (tty_acs_needed(tty)) { log_debug("%s: using capabilities for ACS", c->name); @@ -472,7 +484,8 @@ tty_stop_tty(struct tty *tty) tty_raw(tty, tty_term_string(tty->term, TTYC_RMACS)); tty_raw(tty, tty_term_string(tty->term, TTYC_SGR0)); tty_raw(tty, tty_term_string(tty->term, TTYC_RMKX)); - tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); + if (options_get_number(global_options, "clear-on-attach")) + tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); if (tty->cstyle != SCREEN_CURSOR_DEFAULT) { if (tty_term_has(tty->term, TTYC_SE)) tty_raw(tty, tty_term_string(tty->term, TTYC_SE)); @@ -497,7 +510,10 @@ tty_stop_tty(struct tty *tty) if (tty_use_margin(tty)) tty_raw(tty, tty_term_string(tty->term, TTYC_DSMG)); - tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); + if (options_get_number(global_options, "clear-on-attach")) + tty_raw(tty, tty_term_string(tty->term, TTYC_RMCUP)); + else + tty_raw(tty, tty_term_string(tty->term, TTYC_CLEAR)); if (tty->term->flags & TERM_VT100LIKE) tty_raw(tty, "\033[?2031l");