Skip to content

Commit 681fc3f

Browse files
committed
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)
1 parent 6601b62 commit 681fc3f

File tree

5 files changed

+111
-3
lines changed

5 files changed

+111
-3
lines changed

runtime/doc/term.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ Added by Vim (there are no standard codes for these):
373373
t_Ri restore icon text from stack *t_Ri* *'t_Ri'*
374374
t_TE end of "raw" mode *t_TE* *'t_TE'*
375375
t_TI put terminal into "raw" mode *t_TI* *'t_TI'*
376+
t_fd disable focus-event tracking *t_TI* *'t_TI'*
377+
|xterm-focus-event|
378+
t_fe enable focus-event tracking *t_TI* *'t_TI'*
379+
|xterm-focus-event|
376380

377381
Some codes have a start, middle and end part. The start and end are defined
378382
by the termcap option, the middle part is text.
@@ -546,6 +550,16 @@ And run "xrdb -merge .Xresources" to make it effective. You can check the
546550
value with the context menu (right mouse button while CTRL key is pressed),
547551
there should be a tick at allow-window-ops.
548552

553+
*xterm-focus-event*
554+
Some terminals including xterm support the focus event tracking feature.
555+
If this feature is enabled by the 't_fe' sequence, special key sequences are
556+
sent from the terminal to Vim every time the terminal gains or loses focus.
557+
Vim fires focus events (|FocusGained|/|FocusLost|) by handling them accordingly.
558+
Focus event tracking is disabled by a 't_fd' sequence when exiting "raw" mode.
559+
If you would like to disable this feature, add the following to your .vimrc:
560+
`set t_fd=`
561+
`set t_fe=`
562+
549563
*termcap-colors*
550564
Note about colors: The 't_Co' option tells Vim the number of colors available.
551565
When it is non-zero, the 't_AB' and 't_AF' options are used to set the color.

src/optiondefs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,6 +2957,8 @@ static struct vimoption options[] =
29572957
p_term("t_EC", T_CEC)
29582958
p_term("t_EI", T_CEI)
29592959
p_term("t_fs", T_FS)
2960+
p_term("t_fd", T_FD)
2961+
p_term("t_fe", T_FE)
29602962
p_term("t_GP", T_CGP)
29612963
p_term("t_IE", T_CIE)
29622964
p_term("t_IS", T_CIS)

src/term.c

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ static char_u *vim_tgetstr(char *s, char_u **pp);
196196

197197
static int detected_8bit = FALSE; // detected 8-bit terminal
198198

199+
#if (defined(UNIX) || defined(VMS))
200+
static int focus_mode = FALSE; // xterm's "focus reporting" availability
201+
static int focus_state = FALSE; // TRUE if the terminal window gains focus
202+
#endif
203+
199204
#ifdef FEAT_TERMRESPONSE
200205
// When the cursor shape was detected these values are used:
201206
// 1: block, 2: underline, 3: vertical bar
@@ -908,6 +913,10 @@ static struct builtin_term builtin_termcaps[] =
908913
{(int)KS_CRT, IF_EB("\033[23;2t", ESC_STR "[23;2t")},
909914
{(int)KS_SSI, IF_EB("\033[22;1t", ESC_STR "[22;1t")},
910915
{(int)KS_SRI, IF_EB("\033[23;1t", ESC_STR "[23;1t")},
916+
# if (defined(UNIX) || defined(VMS))
917+
{(int)KS_FD, IF_EB("\033[?1004l", ESC_STR "[?1004l")},
918+
{(int)KS_FE, IF_EB("\033[?1004h", ESC_STR "[?1004h")},
919+
# endif
911920

912921
{K_UP, IF_EB("\033O*A", ESC_STR "O*A")},
913922
{K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")},
@@ -2044,6 +2053,27 @@ set_termname(char_u *term)
20442053
set_mouse_termcode(KS_MOUSE, (char_u *)"\233M");
20452054
#endif
20462055

2056+
#if (defined(UNIX) || defined(VMS))
2057+
// focus reporting is supported by xterm compatible terminals and tmux.
2058+
if (use_xterm_like_mouse(term))
2059+
{
2060+
char_u name[3];
2061+
name[0] = (int)KS_EXTRA;
2062+
name[2] = NUL;
2063+
2064+
// handle focus in event
2065+
name[1] = (int)KE_FOCUSGAINED;
2066+
add_termcode(name, (char_u *)"\033[I", FALSE);
2067+
2068+
// handle focus out event
2069+
name[1] = (int)KE_FOCUSLOST;
2070+
add_termcode(name, (char_u *)"\033[O", FALSE);
2071+
2072+
focus_mode = TRUE;
2073+
focus_state = TRUE;
2074+
}
2075+
#endif
2076+
20472077
#ifdef USE_TERM_CONSOLE
20482078
// DEFAULT_TERM indicates that it is the machine console.
20492079
if (STRCMP(term, DEFAULT_TERM) != 0)
@@ -2519,7 +2549,10 @@ out_flush(void)
25192549
if (ch_log_output)
25202550
{
25212551
out_buf[len] = NUL;
2522-
ch_log(NULL, "raw terminal output: \"%s\"", out_buf);
2552+
ch_log(NULL, "raw %s output: \"%s\"",
2553+
(gui.in_use && !gui.dying && !gui.starting)
2554+
? "GUI" : "terminal",
2555+
out_buf);
25232556
ch_log_output = FALSE;
25242557
}
25252558
#endif
@@ -3582,6 +3615,13 @@ starttermcap(void)
35823615
out_str(T_CTI); // start "raw" mode
35833616
out_str(T_KS); // start "keypad transmit" mode
35843617
out_str(T_BE); // enable bracketed paste mode
3618+
3619+
#if (defined(UNIX) || defined(VMS))
3620+
// enable xterm's focus reporting mode
3621+
if (focus_mode && *T_FE != NUL)
3622+
out_str(T_FE);
3623+
#endif
3624+
35853625
out_flush();
35863626
termcap_active = TRUE;
35873627
screen_start(); // don't know where cursor is now
@@ -3633,6 +3673,13 @@ stoptermcap(void)
36333673
#ifdef FEAT_JOB_CHANNEL
36343674
ch_log_output = TRUE;
36353675
#endif
3676+
3677+
#if (defined(UNIX) || defined(VMS))
3678+
// disable xterm's focus reporting mode
3679+
if (focus_mode && *T_FD != NUL)
3680+
out_str(T_FD);
3681+
#endif
3682+
36363683
out_str(T_BD); // disable bracketed paste mode
36373684
out_str(T_KE); // stop "keypad transmit" mode
36383685
out_flush();
@@ -5647,6 +5694,45 @@ check_termcode(
56475694
# endif // !USE_ON_FLY_SCROLL
56485695
#endif // FEAT_GUI
56495696

5697+
#if (defined(UNIX) || defined(VMS))
5698+
/*
5699+
* Handle FocusIn/FocusOut event sequences reported by XTerm.
5700+
* (CSI I/CSI O)
5701+
*/
5702+
if (focus_mode
5703+
# ifdef FEAT_GUI
5704+
&& !gui.in_use
5705+
# endif
5706+
&& key_name[0] == KS_EXTRA
5707+
)
5708+
{
5709+
int did_aucmd = FALSE;
5710+
5711+
if (key_name[1] == KE_FOCUSGAINED && !focus_state)
5712+
{
5713+
did_aucmd = apply_autocmds(EVENT_FOCUSGAINED,
5714+
NULL, NULL, FALSE, curbuf);
5715+
did_cursorhold = TRUE;
5716+
focus_state = TRUE;
5717+
key_name[1] = (int)KE_IGNORE;
5718+
}
5719+
else if (key_name[1] == KE_FOCUSLOST && focus_state)
5720+
{
5721+
did_aucmd = apply_autocmds(EVENT_FOCUSLOST,
5722+
NULL, NULL, FALSE, curbuf);
5723+
did_cursorhold = TRUE;
5724+
focus_state = FALSE;
5725+
key_name[1] = (int)KE_IGNORE;
5726+
}
5727+
if (did_aucmd && (State & (NORMAL | INSERT | TERMINAL)))
5728+
{
5729+
// in case a message was displayed: reposition the cursor
5730+
setcursor();
5731+
out_flush();
5732+
}
5733+
}
5734+
#endif
5735+
56505736
/*
56515737
* Change <xHome> to <Home>, <xUp> to <Up>, etc.
56525738
*/

src/term.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,12 @@ enum SpecialKey
109109
KS_CST, // save window title
110110
KS_CRT, // restore window title
111111
KS_SSI, // save icon text
112-
KS_SRI // restore icon text
112+
KS_SRI, // restore icon text
113+
KS_FD, // disable focus event tracking
114+
KS_FE // enable focus event tracking
113115
};
114116

115-
#define KS_LAST KS_SRI
117+
#define KS_LAST KS_FE
116118

117119
/*
118120
* the terminal capabilities are stored in this array
@@ -212,6 +214,8 @@ extern char_u *(term_strings[]); // current terminal strings
212214
#define T_CRT (TERM_STR(KS_CRT)) // restore window title
213215
#define T_SSI (TERM_STR(KS_SSI)) // save icon text
214216
#define T_SRI (TERM_STR(KS_SRI)) // restore icon text
217+
#define T_FD (TERM_STR(KS_FD)) // disable focus event tracking
218+
#define T_FE (TERM_STR(KS_FE)) // enable focus event tracking
215219

216220
typedef enum {
217221
TMODE_COOK, // terminal mode for external cmds and Ex mode

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2345,
753755
/**/
754756
2344,
755757
/**/

0 commit comments

Comments
 (0)