Commit: patch 9.2.0139: Cannot configure terminal resize event

1 view
Skip to first unread message

Christian Brabandt

unread,
Mar 11, 2026, 4:17:01 PM (21 hours ago) Mar 11
to vim...@googlegroups.com
patch 9.2.0139: Cannot configure terminal resize event

Commit: https://github.com/vim/vim/commit/c970b470fb2d23ae35b2b598c70884a90fb2df04
Author: Foxe Chen <chen...@gmail.com>
Date: Wed Mar 11 20:03:36 2026 +0000

patch 9.2.0139: Cannot configure terminal resize event

Problem: Cannot configure terminal resize event
Solution: Add the 'termresize' option and allow to use in-band window
resize events (Foxe Chen).

closes: #19596

Signed-off-by: Foxe Chen <chen...@gmail.com>
Signed-off-by: Christian Brabandt <c...@256bit.org>

diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index c7e010d59..7131e7efa 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt* For Vim version 9.2. Last change: 2026 Mar 04
+*options.txt* For Vim version 9.2. Last change: 2026 Mar 11


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -9096,6 +9096,24 @@ A jump table for the options with a short description can be found at |Q_op|.
<
NOTE: This option is reset when 'compatible' is set.

+ *'termresize* *'trz'*
+'termresize' 'trz' number (default "")
+ global
+ {only available in Unix, does not work in the GUI}
+ Determines the method to use for detecting window resize events,
+ possible values are:
+ "sigwinch": Use the SIGWINCH signal.
+ "inband": Receive resize events from the terminal via escape
+ sequences (recommended if supported by terminal).
+ "": Automatically choose depending on terminal.
+
+ The SIGWINCH handler is always available. If set to "inband" and the
+ terminal does not support in-band window resize events, then the
+ SIGWINCH handler will be used instead as a fallback. If set to ""
+ (empty option), then "inband" will be used if Vim detects that the
+ terminal supports it, otherwise "sigwinch".
+
+
*'termsync'* *'tsy'*
'termsync' 'tsy' boolean (default off)
global
diff --git a/runtime/doc/tags b/runtime/doc/tags
index a000eacbd..4fe69bace 100644
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -1237,6 +1237,7 @@ $quote eval.txt /*$quote*
'termbidi' options.txt /*'termbidi'*
'termencoding' options.txt /*'termencoding'*
'termguicolors' options.txt /*'termguicolors'*
+'termresize options.txt /*'termresize*
'termsync' options.txt /*'termsync'*
'termwinkey' options.txt /*'termwinkey'*
'termwinscroll' options.txt /*'termwinscroll'*
@@ -1269,6 +1270,7 @@ $quote eval.txt /*$quote*
'tplo' options.txt /*'tplo'*
'tpm' options.txt /*'tpm'*
'tr' options.txt /*'tr'*
+'trz' options.txt /*'trz'*
'ts' options.txt /*'ts'*
'tsl' options.txt /*'tsl'*
'tsr' options.txt /*'tsr'*
diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt
index 5d122ef41..6bbb700e9 100644
--- a/runtime/doc/version9.txt
+++ b/runtime/doc/version9.txt
@@ -1,4 +1,4 @@
-*version9.txt* For Vim version 9.2. Last change: 2026 Mar 08
+*version9.txt* For Vim version 9.2. Last change: 2026 Mar 11


VIM REFERENCE MANUAL by Bram Moolenaar
@@ -52616,6 +52616,7 @@ Options: ~
"maxheight" suboption to use several lines.
't_BS' Begin synchronized update.
't_ES' End synchronized update.
+'termresize' Method for handling terminal resize events.
'termsync' Enable support for terminal DEC 2026 sync mode.
'winhighlight' Window-local highlight group mappings.

diff --git a/runtime/optwin.vim b/runtime/optwin.vim
index 7d30f010b..e20fda26b 100644
--- a/runtime/optwin.vim
+++ b/runtime/optwin.vim
@@ -1,7 +1,7 @@
" These commands create the option window.
"
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2026 Mar 04
+" Last Change: 2026 Mar 11
" Former Maintainer: Bram Moolenaar <Br...@vim.org>

" If there already is an option window, jump to that one.
@@ -385,6 +385,10 @@ call <SID>AddOption("window", gettext("number of lines to scroll for CTRL-F and
call append("$", " set window=" . &window)
call <SID>AddOption("lazyredraw", gettext("don't redraw while executing macros"))
call <SID>BinOptionG("lz", &lz)
+if has("unix")
+ call <SID>AddOption("termresize", gettext("configure method of receiving terminal size changes"))
+ call <SID>BinOptionG("trz", &trz)
+endif
call <SID>AddOption("termsync", gettext("enable terminal sync mode"))
call <SID>BinOptionG("tsy", &tsy)
if has("reltime")
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index 5caee0534..dc0356eae 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -2,7 +2,7 @@
" Language: Vim script
" Maintainer: Hirohito Higashi <h.east.727 ATMARK gmail.com>
" Doug Kearns <dougk...@gmail.com>
-" Last Change: 2026 Mar 04
+" Last Change: 2026 Mar 11
" Former Maintainer: Charles E. Campbell

" DO NOT CHANGE DIRECTLY.
@@ -70,9 +70,9 @@ syn keyword vimOption contained efm errorformat ek esckeys ei eventignore eiw ev
syn keyword vimOption contained hi history hk hkmap hkp hkmapp hls hlsearch icon iconstring ic ignorecase imaf imactivatefunc imak imactivatekey imc imcmdline imd imdisable imi iminsert ims imsearch imsf imstatusfunc imst imstyle inc include inex includeexpr is incsearch inde indentexpr indk indentkeys inf infercase im insertmode isf isfname isi isident isk iskeyword isp isprint js joinspaces jop jumpoptions key kmp keymap km keymodel kpc keyprotocol kp keywordprg lmap langmap lm langmenu lnr langnoremap lrm langremap ls laststatus lz lazyredraw lhi lhistory lbr linebreak lines lsp linespace lisp lop lispoptions lw lispwords list lcs listchars lpl loadplugins luadll magic mef makeef menc makeencoding mp makeprg mps matchpairs mat matchtime mco maxcombine mfd maxfuncdepth skipwhite nextgroup=vimSetEqual,vimSetMod
syn keyword vimOption contained mmd maxmapdepth mm maxmem mmp maxmempattern mmt maxmemtot msc maxsearchcount mis menuitems mopt messagesopt msm mkspellmem ml modeline mle modelineexpr mls modelines ma modifiable mod modified more mouse mousef mousefocus mh mousehide mousem mousemodel mousemev mousemoveevent mouses mouseshape mouset mousetime mzq mzquantum mzschemedll mzschemegcdll nf nrformats nu number nuw numberwidth ofu omnifunc odev opendevice opfunc operatorfunc ost osctimeoutlen pp packpath para paragraphs paste pt pastetoggle pex patchexpr pm patchmode pa path perldll pi preserveindent pvh previewheight pvp previewpopup pvw previewwindow pdev printdevice penc printencoding pexpr printexpr pfn printfont pheader printheader pmbcs printmbcharset pmbfn printmbfont skipwhite nextgroup=vimSetEqual,vimSetMod
syn keyword vimOption contained popt printoptions prompt pb pumborder ph pumheight pmw pummaxwidth pw pumwidth pythondll pythonhome pythonthreedll pythonthreehome pyx pyxversion qftf quickfixtextfunc qe quoteescape ro readonly rdt redrawtime re regexpengine rnu relativenumber remap rop renderoptions report rs restorescreen ri revins rl rightleft rlc rightleftcmd rubydll ru ruler ruf rulerformat rtp runtimepath scr scroll scb scrollbind scf scrollfocus sj scrolljump so scrolloff sbo scrollopt sect sections secure sel selection slm selectmode ssop sessionoptions sh shell shcf shellcmdflag sp shellpipe shq shellquote srr shellredir ssl shellslash stmp shelltemp st shelltype sxe shellxescape sxq shellxquote sr shiftround sw shiftwidth shm shortmess sn shortname sbr showbreak skipwhite nextgroup=vimSetEqual,vimSetMod
-syn keyword vimOption contained sc showcmd sloc showcmdloc sft showfulltag sm showmatch smd showmode stal showtabline stpl showtabpanel ss sidescroll siso sidescrolloff scl signcolumn scs smartcase si smartindent sta smarttab sms smoothscroll sts softtabstop spell spc spellcapcheck spf spellfile spl spelllang spo spelloptions sps spellsuggest sb splitbelow spk splitkeep spr splitright sol startofline stl statusline stlo statuslineopt su suffixes sua suffixesadd swf swapfile sws swapsync swb switchbuf smc synmaxcol syn syntax tcl tabclose tal tabline tpm tabpagemax tpl tabpanel tplo tabpanelopt ts tabstop tbs tagbsearch tc tagcase tfu tagfunc tl taglength tr tagrelative tag tags tgst tagstack tcldll term tbidi termbidi tenc termencoding tgc termguicolors tsy termsync skipwhite nextgroup=vimSetEqual,vimSetMod
-syn keyword vimOption contained twk termwinkey twsl termwinscroll tws termwinsize twt termwintype terse ta textauto tx textmode tw textwidth tsr thesaurus tsrfu thesaurusfunc top tildeop to timeout tm timeoutlen title titlelen titleold titlestring tb toolbar tbis toolbariconsize ttimeout ttm ttimeoutlen tbi ttybuiltin tf ttyfast ttym ttymouse tsl ttyscroll tty ttytype udir undodir udf undofile ul undolevels ur undoreload uc updatecount ut updatetime vsts varsofttabstop vts vartabstop vbs verbose vfile verbosefile vdir viewdir vop viewoptions vi viminfo vif viminfofile ve virtualedit vb visualbell warn wiv weirdinvert ww whichwrap wc wildchar wcm wildcharm wig wildignore wic wildignorecase wmnu wildmenu wim wildmode wop wildoptions wak winaltkeys wcr wincolor wi window skipwhite nextgroup=vimSetEqual,vimSetMod
-syn keyword vimOption contained wfb winfixbuf wfh winfixheight wfw winfixwidth wh winheight whl winhighlight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes skipwhite nextgroup=vimSetEqual,vimSetMod
+syn keyword vimOption contained sc showcmd sloc showcmdloc sft showfulltag sm showmatch smd showmode stal showtabline stpl showtabpanel ss sidescroll siso sidescrolloff scl signcolumn scs smartcase si smartindent sta smarttab sms smoothscroll sts softtabstop spell spc spellcapcheck spf spellfile spl spelllang spo spelloptions sps spellsuggest sb splitbelow spk splitkeep spr splitright sol startofline stl statusline stlo statuslineopt su suffixes sua suffixesadd swf swapfile sws swapsync swb switchbuf smc synmaxcol syn syntax tcl tabclose tal tabline tpm tabpagemax tpl tabpanel tplo tabpanelopt ts tabstop tbs tagbsearch tc tagcase tfu tagfunc tl taglength tr tagrelative tag tags tgst tagstack tcldll term tbidi termbidi tenc termencoding tgc termguicolors trz termresize skipwhite nextgroup=vimSetEqual,vimSetMod
+syn keyword vimOption contained tsy termsync twk termwinkey twsl termwinscroll tws termwinsize twt termwintype terse ta textauto tx textmode tw textwidth tsr thesaurus tsrfu thesaurusfunc top tildeop to timeout tm timeoutlen title titlelen titleold titlestring tb toolbar tbis toolbariconsize ttimeout ttm ttimeoutlen tbi ttybuiltin tf ttyfast ttym ttymouse tsl ttyscroll tty ttytype udir undodir udf undofile ul undolevels ur undoreload uc updatecount ut updatetime vsts varsofttabstop vts vartabstop vbs verbose vfile verbosefile vdir viewdir vop viewoptions vi viminfo vif viminfofile ve virtualedit vb visualbell warn wiv weirdinvert ww whichwrap wc wildchar wcm wildcharm wig wildignore wic wildignorecase wmnu wildmenu wim wildmode wop wildoptions wak winaltkeys wcr wincolor skipwhite nextgroup=vimSetEqual,vimSetMod
+syn keyword vimOption contained wi window wfb winfixbuf wfh winfixheight wfw winfixwidth wh winheight whl winhighlight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes skipwhite nextgroup=vimSetEqual,vimSetMod

" vimOptions: These are the turn-off setting variants {{{2
" GEN_SYN_VIM: vimOption turn-off, START_STR='syn keyword vimOption contained', END_STR=''
@@ -110,8 +110,8 @@ syn keyword vimOptionVarName contained hi history hk hkmap hkp hkmapp hls hlsear
syn keyword vimOptionVarName contained mfd maxfuncdepth mmd maxmapdepth mm maxmem mmp maxmempattern mmt maxmemtot msc maxsearchcount mis menuitems mopt messagesopt msm mkspellmem ml modeline mle modelineexpr mls modelines ma modifiable mod modified more mouse mousef mousefocus mh mousehide mousem mousemodel mousemev mousemoveevent mouses mouseshape mouset mousetime mzq mzquantum mzschemedll mzschemegcdll nf nrformats nu number nuw numberwidth ofu omnifunc odev opendevice opfunc operatorfunc ost osctimeoutlen pp packpath para paragraphs paste pt pastetoggle pex patchexpr pm patchmode pa path perldll pi preserveindent pvh previewheight pvp previewpopup pvw previewwindow pdev printdevice penc printencoding pexpr printexpr pfn printfont pheader printheader pmbcs printmbcharset
syn keyword vimOptionVarName contained pmbfn printmbfont popt printoptions prompt pb pumborder ph pumheight pmw pummaxwidth pw pumwidth pythondll pythonhome pythonthreedll pythonthreehome pyx pyxversion qftf quickfixtextfunc qe quoteescape ro readonly rdt redrawtime re regexpengine rnu relativenumber remap rop renderoptions report rs restorescreen ri revins rl rightleft rlc rightleftcmd rubydll ru ruler ruf rulerformat rtp runtimepath scr scroll scb scrollbind scf scrollfocus sj scrolljump so scrolloff sbo scrollopt sect sections secure sel selection slm selectmode ssop sessionoptions sh shell shcf shellcmdflag sp shellpipe shq shellquote srr shellredir ssl shellslash stmp shelltemp st shelltype sxe shellxescape sxq shellxquote sr shiftround sw shiftwidth shm shortmess
syn keyword vimOptionVarName contained sn shortname sbr showbreak sc showcmd sloc showcmdloc sft showfulltag sm showmatch smd showmode stal showtabline stpl showtabpanel ss sidescroll siso sidescrolloff scl signcolumn scs smartcase si smartindent sta smarttab sms smoothscroll sts softtabstop spell spc spellcapcheck spf spellfile spl spelllang spo spelloptions sps spellsuggest sb splitbelow spk splitkeep spr splitright sol startofline stl statusline stlo statuslineopt su suffixes sua suffixesadd swf swapfile sws swapsync swb switchbuf smc synmaxcol syn syntax tcl tabclose tal tabline tpm tabpagemax tpl tabpanel tplo tabpanelopt ts tabstop tbs tagbsearch tc tagcase tfu tagfunc tl taglength tr tagrelative tag tags tgst tagstack tcldll term tbidi termbidi tenc termencoding
-syn keyword vimOptionVarName contained tgc termguicolors tsy termsync twk termwinkey twsl termwinscroll tws termwinsize twt termwintype terse ta textauto tx textmode tw textwidth tsr thesaurus tsrfu thesaurusfunc top tildeop to timeout tm timeoutlen title titlelen titleold titlestring tb toolbar tbis toolbariconsize ttimeout ttm ttimeoutlen tbi ttybuiltin tf ttyfast ttym ttymouse tsl ttyscroll tty ttytype udir undodir udf undofile ul undolevels ur undoreload uc updatecount ut updatetime vsts varsofttabstop vts vartabstop vbs verbose vfile verbosefile vdir viewdir vop viewoptions vi viminfo vif viminfofile ve virtualedit vb visualbell warn wiv weirdinvert ww whichwrap wc wildchar wcm wildcharm wig wildignore wic wildignorecase wmnu wildmenu wim wildmode wop wildoptions
-syn keyword vimOptionVarName contained wak winaltkeys wcr wincolor wi window wfb winfixbuf wfh winfixheight wfw winfixwidth wh winheight whl winhighlight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes
+syn keyword vimOptionVarName contained tgc termguicolors trz termresize tsy termsync twk termwinkey twsl termwinscroll tws termwinsize twt termwintype terse ta textauto tx textmode tw textwidth tsr thesaurus tsrfu thesaurusfunc top tildeop to timeout tm timeoutlen title titlelen titleold titlestring tb toolbar tbis toolbariconsize ttimeout ttm ttimeoutlen tbi ttybuiltin tf ttyfast ttym ttymouse tsl ttyscroll tty ttytype udir undodir udf undofile ul undolevels ur undoreload uc updatecount ut updatetime vsts varsofttabstop vts vartabstop vbs verbose vfile verbosefile vdir viewdir vop viewoptions vi viminfo vif viminfofile ve virtualedit vb visualbell warn wiv weirdinvert ww whichwrap wc wildchar wcm wildcharm wig wildignore wic wildignorecase wmnu wildmenu wim wildmode
+syn keyword vimOptionVarName contained wop wildoptions wak winaltkeys wcr wincolor wi window wfb winfixbuf wfh winfixheight wfw winfixwidth wh winheight whl winhighlight wmh winminheight wmw winminwidth winptydll wiw winwidth wse wlseat wst wlsteal wtm wltimeoutlen wrap wm wrapmargin ws wrapscan write wa writeany wb writebackup wd writedelay xtermcodes
" GEN_SYN_VIM: vimOption term output code variable, START_STR='syn keyword vimOptionVarName contained', END_STR=''
syn keyword vimOptionVarName contained t_AB t_AF t_AU t_AL t_al t_bc t_BE t_BD t_cd t_ce t_Ce t_CF t_cl t_cm t_Co t_CS t_Cs t_cs t_CV t_da t_db t_DL t_dl t_ds t_Ds t_EC t_EI t_fs t_fd t_fe t_GP t_IE t_IS t_ke t_ks t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RF t_RB t_RC t_RI t_Ri t_RK t_RS t_RT t_RV t_Sb t_SC t_se t_Sf t_SH t_SI t_Si t_so t_SR t_sr t_ST t_Te t_te t_TE t_ti t_TI t_Ts t_ts t_u7 t_ue t_us t_Us t_ut t_vb t_ve t_vi t_VS t_vs t_WP t_WS t_XM t_xn t_xs t_ZH t_ZR t_8f t_8b t_8u t_xo t_BS t_ES
syn keyword vimOptionVarName contained t_F1 t_F2 t_F3 t_F4 t_F5 t_F6 t_F7 t_F8 t_F9 t_k1 t_K1 t_k2 t_k3 t_K3 t_k4 t_K4 t_k5 t_K5 t_k6 t_K6 t_k7 t_K7 t_k8 t_K8 t_k9 t_K9 t_KA t_kb t_kB t_KB t_KC t_kd t_kD t_KD t_KE t_KF t_KG t_kh t_KH t_kI t_KI t_KJ t_KK t_kl t_KL t_kN t_kP t_kr t_ku
diff --git a/src/gui.c b/src/gui.c
index edf64368f..4238b8b73 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -78,6 +78,9 @@ gui_start(char_u *arg UNUSED)
cursor_on(); // needed for ":gui" in .vimrc
full_screen = FALSE;

+ // If GUI fails to start, then we will recover afterwards
+ term_disable_dec();
+
#ifdef GUI_MAY_FORK
++recursive;
/*
@@ -141,6 +144,9 @@ gui_start(char_u *arg UNUSED)
termcapinit(old_term);
settmode(TMODE_RAW); // restart RAW mode
set_title_defaults(); // set 'title' and 'icon' again
+#ifdef UNIX
+ term_set_win_resize(true);
+#endif
#if defined(GUI_MAY_SPAWN) && defined(EXPERIMENTAL_GUI_CMD)
if (msg != NULL)
emsg(msg);
@@ -148,11 +154,8 @@ gui_start(char_u *arg UNUSED)
}
#ifdef HAVE_CLIPMETHOD
else
- {
// Reset clipmethod to CLIPMETHOD_NONE
choose_clipmethod();
- term_set_sync_output(TERM_SYNC_OUTPUT_OFF);
- }
#endif

#if defined(FEAT_SOCKETSERVER) && defined(FEAT_GUI_GTK)
diff --git a/src/main.c b/src/main.c
index 10828933d..4579690e1 100644
--- a/src/main.c
+++ b/src/main.c
@@ -893,7 +893,7 @@ vim_main2(void)

may_req_bg_color();

- may_req_sync_output();
+ may_req_dec_setting();
# endif

// start in insert mode
@@ -1857,7 +1857,7 @@ getout(int exitval)
free_cmd_argsW();
#endif

- term_set_sync_output(TERM_SYNC_OUTPUT_OFF);
+ term_disable_dec();

mch_exit(exitval);
}
diff --git a/src/option.h b/src/option.h
index 5f656f9b1..966b0bdea 100644
--- a/src/option.h
+++ b/src/option.h
@@ -1035,6 +1035,9 @@ EXTERN char_u *p_tenc; // 'termencoding'
#ifdef FEAT_TERMGUICOLORS
EXTERN int p_tgc; // 'termguicolors'
#endif
+#ifdef UNIX
+EXTERN char_u *p_trz; // 'termresize'
+#endif
EXTERN int p_tsy; // 'termsync'
#ifdef FEAT_TERMINAL
EXTERN long p_twsl; // 'termwinscroll'
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 6ab34ff9e..d89b12523 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -2659,6 +2659,15 @@ static struct vimoption options[] =
#else
(char_u*)NULL, PV_NONE, NULL, NULL,
{(char_u *)FALSE, (char_u *)FALSE}
+#endif
+ SCTX_INIT},
+ {"termresize", "trz", P_STRING|P_VI_DEF,
+#ifdef UNIX
+ (char_u *)&p_trz, PV_NONE, did_set_termresize, expand_set_termresize,
+ {(char_u *)"", (char_u *)0}
+#else
+ (char_u *)NULL, PV_NONE, NULL, NULL,
+ {(char_u *)NULL, (char_u *)0L}
#endif
SCTX_INIT},
{"termsync", "tsy", P_BOOL|P_VI_DEF,
diff --git a/src/optionstr.c b/src/optionstr.c
index b94824d45..aefb78ee8 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -150,6 +150,9 @@ static char *(p_csl_values[]) = {"slash", "backslash", NULL};
#ifdef FEAT_SIGNS
static char *(p_scl_values[]) = {"yes", "no", "auto", "number", NULL};
#endif
+#ifdef UNIX
+static char *(p_trz_values[]) = {"inband", "sigwinch", "", NULL};
+#endif
#if defined(MSWIN) && defined(FEAT_TERMINAL)
static char *(p_twt_values[]) = {"winpty", "conpty", "", NULL};
#endif
@@ -4465,6 +4468,37 @@ did_set_term_option(optset_T *args)
return NULL;
}

+
+#ifdef UNIX
+/*
+ * The 'termresize' option is changed.
+ */
+ char *
+did_set_termresize(optset_T *args UNUSED)
+{
+ // If empty or "inband", then attempt to enable in-band resize events.
+ if (*p_trz == NUL || STRCMP(p_trz, "inband") == 0)
+ term_set_win_resize(true);
+ else if (STRCMP(p_trz, "sigwinch") == 0)
+ term_set_win_resize(false);
+ else
+ return e_invalid_argument;
+
+ return NULL;
+}
+
+ int
+expand_set_termresize(optexpand_T *args, int *numMatches, char_u ***matches)
+{
+ return expand_set_opt_string(
+ args,
+ p_trz_values,
+ ARRAY_LENGTH(p_trz_values) - 1,
+ numMatches,
+ matches);
+}
+#endif
+
#if defined(FEAT_TERMINAL)
/*
* The 'termwinkey' option is changed.
diff --git a/src/os_unix.c b/src/os_unix.c
index 3bd2942ca..03f764909 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -1568,6 +1568,14 @@ mch_init(void)
#ifdef FEAT_CYGWIN_WIN32_CLIPBOARD
win_clip_init();
#endif
+}
+
+ void
+set_sigwinch_handler(void)
+{
+#if defined(SIGWINCH)
+ mch_signal(SIGWINCH, sig_winch);
+#endif
}

static void
diff --git a/src/po/vim.pot b/src/po/vim.pot
index 32898088c..c9d9a0aa8 100644
--- a/src/po/vim.pot
+++ b/src/po/vim.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Vim
"
"Report-Msgid-Bugs-To: vim...@vim.org
"
-"POT-Creation-Date: 2026-03-04 21:06+0000
"
+"POT-Creation-Date: 2026-03-11 20:02+0000
"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>
"
"Language-Team: LANGUAGE <L...@li.org>
"
@@ -9445,6 +9445,9 @@ msgstr ""
msgid "don't redraw while executing macros"
msgstr ""

+msgid "configure method of receiving terminal size changes"
+msgstr ""
+
msgid "enable terminal sync mode"
msgstr ""

diff --git a/src/proto/optionstr.pro b/src/proto/optionstr.pro
index e4e39e759..be8b8e97b 100644
--- a/src/proto/optionstr.pro
+++ b/src/proto/optionstr.pro
@@ -180,6 +180,8 @@ char *did_set_tagcase(optset_T *args);
int expand_set_tagcase(optexpand_T *args, int *numMatches, char_u ***matches);
char *did_set_term(optset_T *args);
char *did_set_term_option(optset_T *args);
+char *did_set_termresize(optset_T *args);
+int expand_set_termresize(optexpand_T *args, int *numMatches, char_u ***matches);
char *did_set_termwinkey(optset_T *args);
char *did_set_termwinsize(optset_T *args);
char *did_set_termwintype(optset_T *args);
diff --git a/src/proto/os_unix.pro b/src/proto/os_unix.pro
index 41efd0f2c..5abaae621 100644
--- a/src/proto/os_unix.pro
+++ b/src/proto/os_unix.pro
@@ -10,6 +10,7 @@ void mch_delay(long msec, int flags);
int mch_stackcheck(char *p);
void mch_suspend(void);
void mch_init(void);
+void set_sigwinch_handler(void);
void reset_signals(void);
int vim_handle_signal(int sig);
int mch_check_win(int argc, char **argv);
diff --git a/src/proto/term.pro b/src/proto/term.pro
index 862864b39..80f9b00e9 100644
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -96,6 +96,8 @@ void swap_tcap(void);
void ansi_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx);
void cterm_color2rgb(int nr, char_u *r, char_u *g, char_u *b, char_u *ansi_idx);
int term_replace_keycodes(char_u *ta_buf, int ta_len, int len_arg);
-void may_req_sync_output(void);
+void may_req_dec_setting(void);
+void term_disable_dec(void);
+void term_set_win_resize(bool state);
void term_set_sync_output(int flags);
/* vim: set ft=c : */
diff --git a/src/term.c b/src/term.c
index 5c3212b26..21c529db9 100644
--- a/src/term.c
+++ b/src/term.c
@@ -133,6 +133,11 @@ static termrequest_T xcc_status = TERMREQUEST_INIT;
// Request synchronized output report
static termrequest_T sync_output_status = TERMREQUEST_INIT;

+#ifdef UNIX
+// Request in-band window resize events report
+static termrequest_T win_resize_status = TERMREQUEST_INIT;
+#endif
+
#ifdef FEAT_TERMRESPONSE
# ifdef FEAT_TERMINAL
// Request foreground color report:
@@ -169,6 +174,9 @@ static termrequest_T *all_termrequests[] = {
&rcs_status,
&winpos_status,
&sync_output_status,
+# ifdef UNIX
+ &win_resize_status,
+# endif
NULL
};

@@ -246,6 +254,13 @@ static int sync_output_setting = 0;
// == 0: No synchronized output
static int sync_output_state = 0;

+#ifdef UNIX
+// DEC mode 2048 (in-band window resize events)
+// https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83
+static int win_resize_setting = 0;
+static bool win_resize_enabled = false;
+#endif
+
/*
* The builtin termcap entries.
*
@@ -5594,7 +5609,7 @@ handle_csi_function_key(
*
* - DA1 query response: {lead}?...;c
*
- * - DEC mode 2026 response (synchronized output): {lead}?2026;{mode}$y
+ * - DECRPM response: {lead}?2026;{mode}$y
*
* Return 0 for no match, -1 for partial match, > 0 for full match.
*/
@@ -5724,8 +5739,9 @@ handle_csi(
key_name[1] = (int)KE_IGNORE;
}

- // DEC 2026 mode response (for 'termsync' option)
- else if (first == '?' && trail == 'y' && argc == 2 && arg[0] == 2026)
+ // DECRPM mode 2026 or 2048.
+ else if (first == '?' && trail == 'y' && argc == 2
+ && (arg[0] == 2026 || arg[0] == 2048))
{
int setting = arg[1];

@@ -5735,16 +5751,43 @@ handle_csi(

if (setting >= 0 && setting <= 4)
{
- sync_output_setting = setting;
- LOG_TRN("Received DEC 2026 mode: %s", tp);
- sync_output_status.tr_progress = STATUS_GOT;
+ LOG_TRN("Received DECRPM mode %d: %s", arg[0], tp);
+
+ switch (arg[0])
+ {
+ case 2026:
+ sync_output_setting = setting;
+ sync_output_status.tr_progress = STATUS_GOT;
+ set_option_value_give_err((char_u *)"termsync",
+ setting == 1 || setting == 2, NULL, 0);
+ break;
+#ifdef UNIX
+ case 2048:
+ win_resize_status.tr_progress = STATUS_GOT;
+ win_resize_setting = setting;

- set_option_value_give_err((char_u *)"termsync",
- setting == 1 || setting == 2, NULL, 0);
+ term_set_win_resize(true);
+ break;
+#endif
+ }
}
else
- LOG_TRN("Unknown synchronized output setting %d", setting);
+ LOG_TRN("Unknown DECRPM mode %d setting %d", arg[0], setting);
+ }
+
+#ifdef UNIX
+ // In-band window resize event
+ else if (win_resize_enabled && argc >= 3 && arg[0] == 48)
+ {
+ int height = arg[1], width = arg[2];
+
+ *slen = csi_len;
+ key_name[0] = (int)KS_EXTRA;
+ key_name[1] = (int)KE_IGNORE;
+
+ set_shellsize(width, height, true);
}
+#endif

// Version string: Eat it when there is at least one digit and
// it ends in 'c'
@@ -7855,26 +7898,107 @@ term_replace_keycodes(char_u *ta_buf, int ta_len, int len_arg)

#ifdef FEAT_TERMRESPONSE
/*
- * Query the setting for DEC mode 2026 (synchronized output) from the terminal.
+ * Query the setting for the following DEC modes from the terminal:
+ * - DEC mode 2026 (synchronized output)
+ * - DEC mode 2048 (window resize events)
*/
void
-may_req_sync_output(void)
+may_req_dec_setting(void)
{
- if (can_get_termresponse() && starting == 0
- && sync_output_status.tr_progress == STATUS_GET)
+ if (can_get_termresponse() && starting == 0)
{
- MAY_WANT_TO_LOG_THIS;
- LOG_TR1("Sending synchronized output request");
+ bool didit = false;

- out_str((char_u *)" [?2026$p");
- termrequest_sent(&sync_output_status);
+ if (sync_output_status.tr_progress == STATUS_GET)
+ {
+ MAY_WANT_TO_LOG_THIS;
+ LOG_TR1("Sending synchronized output request");

- // check for the characters now, otherwise they might be eaten by
- // get_keystroke()
- out_flush();
- (void)vpeekc_nomap();
+ out_str((char_u *)" [?2026$p");
+ termrequest_sent(&sync_output_status);
+ didit = true;
+ }
+
+# ifdef UNIX
+ if (win_resize_status.tr_progress == STATUS_GET)
+ {
+ MAY_WANT_TO_LOG_THIS;
+ LOG_TR1("Sending in-band window resize events request");
+
+ out_str((char_u *)" [?2048$p");
+ termrequest_sent(&win_resize_status);
+ didit = true;
+ }
+# endif
+
+ if (didit)
+ {
+ // check for the characters now, otherwise they might be eaten by
+ // get_keystroke()
+ out_flush();
+ (void)vpeekc_nomap();
+ }
}
+}
+#endif
+
+/*
+ * Should be called when cleaning up terminal state.
+ */
+ void
+term_disable_dec(void)
+{
+ term_set_sync_output(TERM_SYNC_OUTPUT_OFF);
+#ifdef UNIX
+ term_set_win_resize(false);
+#endif
+ // Make sure to always flush the output buffer, because this may be called
+ // before starting the GUI
+ out_flush();
+}

+#ifdef UNIX
+/*
+ * Enable or disable receiving in-band window resize events from the terminal.
+ * If "state" is true, then if the terminal supports DEC mode 2048 and
+ * 'termresize' is "" or "inband", then enable it and disable the SIGWINCH
+ * signal handling. Otherwise disable the mode if it is enabled and reinstall
+ * the SIGWINCH handler.
+ */
+ void
+term_set_win_resize(bool state)
+{
+# ifdef FEAT_GUI
+ bool in_gui = gui.in_use;
+# else
+ bool in_gui = false;
+# endif
+
+ if (state && in_gui)
+ return;
+
+ if (!state || win_resize_setting == 0 || win_resize_setting == 4)
+ {
+ // Make sure it update internal window size if DEC mode 2048 is
+ // unavailable now.
+ if (win_resize_enabled)
+ {
+ set_shellsize(0, 0, false);
+ set_sigwinch_handler();
+ out_str((char_u *)" [?2048l");
+ }
+ win_resize_enabled = false;
+ }
+ else if ((*p_trz == NUL || STRCMP(p_trz, "inband") == 0)
+ && !win_resize_enabled)
+ {
+ if (win_resize_setting == 2)
+ out_str((char_u *)" [?2048h");
+# ifdef SIGWINCH
+ mch_signal(SIGWINCH, SIG_DFL);
+# endif
+ win_resize_enabled = true;
+ }
}
#endif

diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim
index 43c75693e..e5f31259e 100644
--- a/src/testdir/test_termcodes.vim
+++ b/src/testdir/test_termcodes.vim
@@ -2966,4 +2966,73 @@ func Test_term_rgb_response()
set t_RF= t_RB=
endfunc

+" Test in-band window resize events (DEC mode 2048).
+" https://gist.github.com/rockorager/e695fb2924d36b2bcf1fff4a3704bd83
+func Test_term_win_resize()
+ CheckRunVimInTerminal
+
+ let lines =<< trim END
+ vim9script
+
+ autocmd VimResized * writefile([$"{&lines} {&columns}"], "XTestWinResizeResult")
+ END
+ call writefile(lines, 'XTestWinResize', 'D')
+ defer delete("XTestWinResizeResult")
+
+ let buf = RunVimInTerminal('-S XTestWinResize', #{rows: 15, cols: 20})
+
+ " Send status report
+ call term_sendkeys(buf, "\<Esc>[?2048;1$y")
+ call TermWait(buf)
+
+ " Resize to 50 rows 100 cols
+ call term_sendkeys(buf, "\<Esc>[48;50;100;0;0t")
+ call TermWait(buf)
+
+ call WaitForAssert({-> assert_equal(["50 100"], readfile("XTestWinResizeResult"))})
+
+ " SIGWINCH handler should be uninstalled
+ call job_stop(term_getjob(buf), 28)
+ call TermWait(buf)
+
+ call WaitForAssert({-> assert_equal(["50 100"], readfile("XTestWinResizeResult"))})
+
+ " SIGWINCH handler should be reinstalled again
+ call term_sendkeys(buf, "\<Esc>:set termresize=sigwinch\<CR>")
+ call TermWait(buf)
+
+ call WaitForAssert({-> assert_equal(["15 20"], readfile("XTestWinResizeResult"))})
+
+ call term_sendkeys(buf, "\<Esc>:set termresize=\<CR>")
+ call TermWait(buf)
+
+ call term_sendkeys(buf, "\<Esc>[48;50;30;0;0t")
+ call TermWait(buf)
+
+ call WaitForAssert({-> assert_equal(["50 30"], readfile("XTestWinResizeResult"))})
+
+ " Simulate no support for in-band window resize
+ call term_sendkeys(buf, "\<Esc>[?2048;0$y")
+ call TermWait(buf)
+
+ " Should reinstall SIGWINCH handler
+ call WaitForAssert({-> assert_equal(["15 20"], readfile("XTestWinResizeResult"))})
+
+ call term_setsize(buf, 5, 20)
+ call TermWait(buf)
+ call WaitForAssert({-> assert_equal(["5 20"], readfile("XTestWinResizeResult"))})
+
+ " Setting 'termresize' to "inband" should do nothing if support is not
+ " detected from terminal.
+ call term_sendkeys(buf, "\<Esc>:set termresize=inband\<CR>")
+ call TermWait(buf)
+
+ call term_sendkeys(buf, "\<Esc>[48;50;100;0;0t")
+ call TermWait(buf)
+
+ call WaitForAssert({-> assert_equal(["5 20"], readfile("XTestWinResizeResult"))})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/util/gen_opt_test.vim b/src/testdir/util/gen_opt_test.vim
index e1476001f..c2c5191da 100644
--- a/src/testdir/util/gen_opt_test.vim
+++ b/src/testdir/util/gen_opt_test.vim
@@ -389,6 +389,13 @@ if !has('clipboard')
\ ]
endif

+if has('unix')
+ let test_values['termresize'] = [
+ \ ['', 'sigwinch', 'inband'],
+ \ ['xxx', 'sig']
+ \ ]
+endif
+
" Two lists with values: values that pre- and post-processing in test.
" Clear out t_WS: we don't want to resize the actual terminal.
let test_prepost = {
diff --git a/src/version.c b/src/version.c
index 028abc2f0..ad7d6ab32 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 139,
/**/
138,
/**/
Reply all
Reply to author
Forward
0 new messages