summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-01-14 17:35:21 +0100
committerBram Moolenaar <Bram@vim.org>2021-01-14 17:35:21 +0100
commit681fc3fa782e99fe69ed2c83c3e29109d2d61e1a (patch)
tree7aa5986843ee75f7a1337c18b022cf22841b00c9
parent6601b62943a19d4f8818c3638440663d67a17b6a (diff)
patch 8.2.2345: no focus events in a terminalv8.2.2345
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)
-rw-r--r--runtime/doc/term.txt14
-rw-r--r--src/optiondefs.h2
-rw-r--r--src/term.c88
-rw-r--r--src/term.h8
-rw-r--r--src/version.c2
5 files changed, 111 insertions, 3 deletions
diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt
index 5b7850fe31..0456a8b89b 100644
--- a/runtime/doc/term.txt
+++ b/runtime/doc/term.txt
@@ -373,6 +373,10 @@ Added by Vim (there are no standard codes for these):
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 make it effective. You can check the
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
index 9afa84df5c..6cea0177cb 100644
--- 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
index 9e9a67b921..bf33a1c185 100644
--- a/src/term.c
+++ b/src/term.c
@@ -196,6 +196,11 @@ static char_u *vim_tgetstr(char *s, char_u **pp);
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_termcaps[] =
{(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 <xHome> to <Home>, <xUp> to <Up>, etc.
*/
diff --git a/src/term.h b/src/term.h
index bff901e3cc..a3d8299990 100644
--- 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[]); // current terminal strings
#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
index dc1b7523ca..30a550fe2d 100644
--- 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,