]> granicus.if.org Git - vim/commitdiff
patch 8.2.2345: no focus events in a terminal v8.2.2345
authorBram Moolenaar <Bram@vim.org>
Thu, 14 Jan 2021 16:35:21 +0000 (17:35 +0100)
committerBram Moolenaar <Bram@vim.org>
Thu, 14 Jan 2021 16:35:21 +0000 (17:35 +0100)
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)

runtime/doc/term.txt
src/optiondefs.h
src/term.c
src/term.h
src/version.c

index 5b7850fe3110503d7fae0bc80e8595432285388b..0456a8b89b7ea576642d4b2d46b62e47e947211e 100644 (file)
@@ -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.
index 9afa84df5c5ce9c66792ce74f3f6d9efd2d3fcab..6cea0177cbcbda57149dc64ed50418add31919d8 100644 (file)
@@ -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)
index 9e9a67b9216c210bd5089af05dcb63435e8124cf..bf33a1c185af20bf21f56e5358e9d1fb494089d9 100644 (file)
@@ -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.
         */
index bff901e3ccc9eaab89e7e12d03180aaff3d7c695..a3d8299990b4c28752fb78a1231e626539787140 100644 (file)
@@ -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
index dc1b7523ca91c73c819570284225b78c7c1f3e66..30a550fe2d2bb9e7f4d3bba9dcb23fc48f48da9c 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2345,
 /**/
     2344,
 /**/