Skip to content

Instantly share code, notes, and snippets.

@saitoha
Last active August 12, 2016 18:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saitoha/a013bdfebe368cf1e0306a66b75621f4 to your computer and use it in GitHub Desktop.
Save saitoha/a013bdfebe368cf1e0306a66b75621f4 to your computer and use it in GitHub Desktop.
vim: focus event tracking - version 3
diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt
index 1eea20f..016b8f6 100644
--- a/runtime/doc/term.txt
+++ b/runtime/doc/term.txt
@@ -306,6 +306,10 @@ Added by Vim (there are no standard codes for these):
|xterm-true-color|
t_8b set background color (R, G, B) *t_8b* *'t_8b'*
|xterm-true-color|
+ t_fe enable focus-event tracking *t_fe* *'t_fe'*
+ |xterm-focus-event|
+ t_fd disable focus-event tracking *t_fd* *'t_fd'*
+ |xterm-focus-event|
KEY CODES
Note: Use the <> form if possible
@@ -457,6 +461,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 focus event tracking feature.
+If this feature is enabled by 't_fe' sequence, special key sequences are sent
+from the terminal to Vim every time the terminal gains or loses the focus. Vim
+fires focus events (|FocusGained|/|FocusLost|) by handling them. focus event
+tracking is disabled by 't_fd' sequence when exit "raw" mode. If you wouldn't
+like to use this feature, add the following code to your .vimrc:
+ `set t_fe=`
+ `set t_fd=`
+
*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/option.c b/src/option.c
index ff7973f..18ab19f 100644
--- a/src/option.c
+++ b/src/option.c
@@ -3018,6 +3018,8 @@ static struct vimoption options[] =
p_term("t_ZR", T_CZR)
p_term("t_8f", T_8F)
p_term("t_8b", T_8B)
+ p_term("t_fe", T_FE)
+ p_term("t_fd", T_FD)
/* terminal key codes are not in here */
diff --git a/src/term.c b/src/term.c
index 344fabc..af6ab11 100644
--- a/src/term.c
+++ b/src/term.c
@@ -162,6 +162,10 @@ static char_u *vim_tgetstr(char *s, char_u **pp);
#endif /* HAVE_TGETENT */
static int detected_8bit = FALSE; /* detected 8-bit terminal */
+#if defined(FEAT_AUTOCMD) && (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
static struct builtin_term builtin_termcaps[] =
{
@@ -860,6 +864,10 @@ static struct builtin_term builtin_termcaps[] =
{(int)KS_8F, IF_EB("\033[38;2;%lu;%lu;%lum", ESC_STR "[38;2;%lu;%lu;%lum")},
{(int)KS_8B, IF_EB("\033[48;2;%lu;%lu;%lum", ESC_STR "[48;2;%lu;%lu;%lum")},
# endif
+# if defined(FEAT_AUTOCMD) && (defined(UNIX) || defined(VMS))
+ {(int)KS_FE, IF_EB("\033[?1004h", ESC_STR "[?1004h")},
+ {(int)KS_FD, IF_EB("\033[?1004l", ESC_STR "[?1004l")},
+# endif
{K_UP, IF_EB("\033O*A", ESC_STR "O*A")},
{K_DOWN, IF_EB("\033O*B", ESC_STR "O*B")},
@@ -1825,6 +1833,28 @@ set_termname(char_u *term)
# endif
#endif /* FEAT_MOUSE */
+#if defined(FEAT_AUTOCMD) && (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)
@@ -3142,6 +3172,11 @@ starttermcap(void)
{
out_str(T_TI); /* start termcap mode */
out_str(T_KS); /* start "keypad transmit" mode */
+#if defined(FEAT_AUTOCMD) && (defined(UNIX) || defined(VMS))
+ /* enable xterm's forcus 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 */
@@ -3191,6 +3226,11 @@ stoptermcap(void)
check_for_codes_from_term();
}
#endif
+#if defined(FEAT_AUTOCMD) && (defined(UNIX) || defined(VMS))
+ /* disable xterm's forcus reporting mode */
+ if (focus_mode && T_FD != NUL)
+ out_str(T_FD);
+#endif
out_str(T_KE); /* stop "keypad transmit" mode */
out_flush();
termcap_active = FALSE;
@@ -5234,6 +5274,35 @@ check_termcode(
# endif /* !USE_ON_FLY_SCROLL */
#endif /* FEAT_GUI */
+#if defined(FEAT_AUTOCMD) && (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
+ )
+ {
+ if (key_name[1] == KE_FOCUSGAINED && !focus_state)
+ {
+ 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)
+ {
+ apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
+ did_cursorhold = TRUE;
+ focus_state = FALSE;
+ key_name[1] = (int)KE_IGNORE;
+ }
+ }
+#endif
+
/*
* Change <xHome> to <Home>, <xUp> to <Up>, etc.
*/
diff --git a/src/term.h b/src/term.h
index 4a7391c..608e385 100644
--- a/src/term.h
+++ b/src/term.h
@@ -89,10 +89,12 @@ enum SpecialKey
KS_OP, /* original color pair */
KS_U7, /* request cursor position */
KS_8F, /* set foreground color (RGB) */
- KS_8B /* set background color (RGB) */
+ KS_8B, /* set background color (RGB) */
+ KS_FE, /* enable focus event tracking */
+ KS_FD /* disable focus event tracking */
};
-#define KS_LAST KS_8B
+#define KS_LAST KS_FD
/*
* the terminal capabilities are stored in this array
@@ -170,6 +172,8 @@ extern char_u *(term_strings[]); /* current terminal strings */
#define T_U7 (term_str(KS_U7)) /* request cursor position */
#define T_8F (term_str(KS_8F)) /* set foreground color (RGB) */
#define T_8B (term_str(KS_8B)) /* set background color (RGB) */
+#define T_FE (term_str(KS_FE)) /* enable focus event tracking */
+#define T_FD (term_str(KS_FD)) /* disable focus event tracking */
#define TMODE_COOK 0 /* terminal mode for external cmds and Ex mode */
#define TMODE_SLEEP 1 /* terminal mode for sleeping (cooked but no echo) */
@cvwillegen
Copy link

Line 23: every time the terminal gains or loses focus

@saitoha
Copy link
Author

saitoha commented Aug 12, 2016

@cvwillegen Thanks, fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment