# HG changeset patch # User Bram Moolenaar # Date 1610642705 -3600 # Node ID f98939164e91ee7d3499b7662445dec8f9c2203e # Parent bc6c4127f05465e5421d77f413453bcccf50d266 patch 8.2.2345: no focus events in a terminal Commit: https://github.com/vim/vim/commit/681fc3fa782e99fe69ed2c83c3e29109d2d61e1a Author: Bram Moolenaar Date: Thu Jan 14 17:35:21 2021 +0100 patch 8.2.2345: no focus events in a terminal Problem: No focus events in a terminal. Solution: Add the t_fd and t_fe termcap entries and implement detecting focus events. (Hayaki Saito, Magnus Gro?, closes #7673, closes #609, closes #5526) diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt --- a/runtime/doc/term.txt +++ b/runtime/doc/term.txt @@ -373,6 +373,10 @@ Added by Vim (there are no standard code t_Ri restore icon text from stack *t_Ri* *'t_Ri'* t_TE end of "raw" mode *t_TE* *'t_TE'* t_TI put terminal into "raw" mode *t_TI* *'t_TI'* + t_fd disable focus-event tracking *t_TI* *'t_TI'* + |xterm-focus-event| + t_fe enable focus-event tracking *t_TI* *'t_TI'* + |xterm-focus-event| Some codes have a start, middle and end part. The start and end are defined by the termcap option, the middle part is text. @@ -546,6 +550,16 @@ And run "xrdb -merge .Xresources" to mak value with the context menu (right mouse button while CTRL key is pressed), there should be a tick at allow-window-ops. + *xterm-focus-event* +Some terminals including xterm support the focus event tracking feature. +If this feature is enabled by the 't_fe' sequence, special key sequences are +sent from the terminal to Vim every time the terminal gains or loses focus. +Vim fires focus events (|FocusGained|/|FocusLost|) by handling them accordingly. +Focus event tracking is disabled by a 't_fd' sequence when exiting "raw" mode. +If you would like to disable this feature, add the following to your .vimrc: + `set t_fd=` + `set t_fe=` + *termcap-colors* Note about colors: The 't_Co' option tells Vim the number of colors available. When it is non-zero, the 't_AB' and 't_AF' options are used to set the color. diff --git a/src/optiondefs.h b/src/optiondefs.h --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -2957,6 +2957,8 @@ static struct vimoption options[] = p_term("t_EC", T_CEC) p_term("t_EI", T_CEI) p_term("t_fs", T_FS) + p_term("t_fd", T_FD) + p_term("t_fe", T_FE) p_term("t_GP", T_CGP) p_term("t_IE", T_CIE) p_term("t_IS", T_CIS) diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -196,6 +196,11 @@ static char_u *vim_tgetstr(char *s, char static int detected_8bit = FALSE; // detected 8-bit terminal +#if (defined(UNIX) || defined(VMS)) +static int focus_mode = FALSE; // xterm's "focus reporting" availability +static int focus_state = FALSE; // TRUE if the terminal window gains focus +#endif + #ifdef FEAT_TERMRESPONSE // When the cursor shape was detected these values are used: // 1: block, 2: underline, 3: vertical bar @@ -908,6 +913,10 @@ static struct builtin_term builtin_termc {(int)KS_CRT, IF_EB("\033[23;2t", ESC_STR "[23;2t")}, {(int)KS_SSI, IF_EB("\033[22;1t", ESC_STR "[22;1t")}, {(int)KS_SRI, IF_EB("\033[23;1t", ESC_STR "[23;1t")}, +# if (defined(UNIX) || defined(VMS)) + {(int)KS_FD, IF_EB("\033[?1004l", ESC_STR "[?1004l")}, + {(int)KS_FE, IF_EB("\033[?1004h", ESC_STR "[?1004h")}, +# endif {K_UP, IF_EB("\033O*A", ESC_STR "O*A")}, {K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")}, @@ -2044,6 +2053,27 @@ set_termname(char_u *term) set_mouse_termcode(KS_MOUSE, (char_u *)"\233M"); #endif +#if (defined(UNIX) || defined(VMS)) + // focus reporting is supported by xterm compatible terminals and tmux. + if (use_xterm_like_mouse(term)) + { + char_u name[3]; + name[0] = (int)KS_EXTRA; + name[2] = NUL; + + // handle focus in event + name[1] = (int)KE_FOCUSGAINED; + add_termcode(name, (char_u *)"\033[I", FALSE); + + // handle focus out event + name[1] = (int)KE_FOCUSLOST; + add_termcode(name, (char_u *)"\033[O", FALSE); + + focus_mode = TRUE; + focus_state = TRUE; + } +#endif + #ifdef USE_TERM_CONSOLE // DEFAULT_TERM indicates that it is the machine console. if (STRCMP(term, DEFAULT_TERM) != 0) @@ -2519,7 +2549,10 @@ out_flush(void) if (ch_log_output) { out_buf[len] = NUL; - ch_log(NULL, "raw terminal output: \"%s\"", out_buf); + ch_log(NULL, "raw %s output: \"%s\"", + (gui.in_use && !gui.dying && !gui.starting) + ? "GUI" : "terminal", + out_buf); ch_log_output = FALSE; } #endif @@ -3582,6 +3615,13 @@ starttermcap(void) out_str(T_CTI); // start "raw" mode out_str(T_KS); // start "keypad transmit" mode out_str(T_BE); // enable bracketed paste mode + +#if (defined(UNIX) || defined(VMS)) + // enable xterm's focus reporting mode + if (focus_mode && *T_FE != NUL) + out_str(T_FE); +#endif + out_flush(); termcap_active = TRUE; screen_start(); // don't know where cursor is now @@ -3633,6 +3673,13 @@ stoptermcap(void) #ifdef FEAT_JOB_CHANNEL ch_log_output = TRUE; #endif + +#if (defined(UNIX) || defined(VMS)) + // disable xterm's focus reporting mode + if (focus_mode && *T_FD != NUL) + out_str(T_FD); +#endif + out_str(T_BD); // disable bracketed paste mode out_str(T_KE); // stop "keypad transmit" mode out_flush(); @@ -5647,6 +5694,45 @@ check_termcode( # endif // !USE_ON_FLY_SCROLL #endif // FEAT_GUI +#if (defined(UNIX) || defined(VMS)) + /* + * Handle FocusIn/FocusOut event sequences reported by XTerm. + * (CSI I/CSI O) + */ + if (focus_mode +# ifdef FEAT_GUI + && !gui.in_use +# endif + && key_name[0] == KS_EXTRA + ) + { + int did_aucmd = FALSE; + + if (key_name[1] == KE_FOCUSGAINED && !focus_state) + { + did_aucmd = apply_autocmds(EVENT_FOCUSGAINED, + NULL, NULL, FALSE, curbuf); + did_cursorhold = TRUE; + focus_state = TRUE; + key_name[1] = (int)KE_IGNORE; + } + else if (key_name[1] == KE_FOCUSLOST && focus_state) + { + did_aucmd = apply_autocmds(EVENT_FOCUSLOST, + NULL, NULL, FALSE, curbuf); + did_cursorhold = TRUE; + focus_state = FALSE; + key_name[1] = (int)KE_IGNORE; + } + if (did_aucmd && (State & (NORMAL | INSERT | TERMINAL))) + { + // in case a message was displayed: reposition the cursor + setcursor(); + out_flush(); + } + } +#endif + /* * Change to , to , etc. */ diff --git a/src/term.h b/src/term.h --- a/src/term.h +++ b/src/term.h @@ -109,10 +109,12 @@ enum SpecialKey KS_CST, // save window title KS_CRT, // restore window title KS_SSI, // save icon text - KS_SRI // restore icon text + KS_SRI, // restore icon text + KS_FD, // disable focus event tracking + KS_FE // enable focus event tracking }; -#define KS_LAST KS_SRI +#define KS_LAST KS_FE /* * the terminal capabilities are stored in this array @@ -212,6 +214,8 @@ extern char_u *(term_strings[]); // c #define T_CRT (TERM_STR(KS_CRT)) // restore window title #define T_SSI (TERM_STR(KS_SSI)) // save icon text #define T_SRI (TERM_STR(KS_SRI)) // restore icon text +#define T_FD (TERM_STR(KS_FD)) // disable focus event tracking +#define T_FE (TERM_STR(KS_FE)) // enable focus event tracking typedef enum { TMODE_COOK, // terminal mode for external cmds and Ex mode diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2345, +/**/ 2344, /**/ 2343,