*** a/src/term.c	2013-04-23 23:51:27.000000000 +0900
--- b/src/term.c	2013-04-23 23:36:31.000000000 +0900
*************** char *UP, *BC, PC;
*** 144,153 ****
--- 144,154 ----
  # define TGETENT(b, t)	tgetent((char *)(b), (char *)(t))
  static char_u *vim_tgetstr __ARGS((char *s, char_u **pp));
  #endif /* HAVE_TGETENT */
  
  static int  detected_8bit = FALSE;	/* detected 8-bit terminal */
+ static int  focus_mode = FALSE;
  
  static struct builtin_term builtin_termcaps[] =
  {
  
  #if defined(FEAT_GUI)
*************** set_termname(term)
*** 1869,1878 ****
--- 1870,1884 ----
  	{
  	    if (use_xterm_mouse())
  		p = NULL;	/* keep existing value, might be "xterm2" */
  	    else
  		p = (char_u *)"xterm";
+ 
+ #   ifdef FEAT_AUTOCMD
+ 	    out_str(IF_EB("\033[?1004h", ESC_STR "[?1004h"));
+ 	    focus_mode = TRUE;
+ #   endif
  	}
  #  endif
  	if (p != NULL)
  	{
  	    set_option_value((char_u *)"ttym", 0L, p, 0);
*************** stoptermcap()
*** 3259,3268 ****
--- 3265,3278 ----
  	    /* Check for termcodes first, otherwise an external program may
  	     * get them. */
  	    check_for_codes_from_term();
  	}
  #endif
+ #ifdef FEAT_AUTOCMD
+ 	if (focus_mode)
+ 	    out_str(IF_EB("\033[?1004l", ESC_STR "[?1004l"));
+ #endif
  	out_str(T_KE);			/* stop "keypad transmit" mode */
  	out_flush();
  	termcap_active = FALSE;
  	cursor_on();			/* just in case it is still off */
  	out_str(T_TE);			/* stop termcap mode */
*************** check_termcode(max_offset, buf, bufsize,
*** 4099,4109 ****
  	    /* URXVT mouse uses <ESC>[#;#;#M, but we are matching <ESC>[ */
  	    || key_name[0] == KS_URXVT_MOUSE
  # ifdef FEAT_MBYTE
  	    || u7_status == U7_SENT
  # endif
!             )
  	{
  	    /* Check for some responses from terminal start with "<Esc>[" or
  	     * CSI.
  	     *
  	     * - xterm version string: <Esc>[>{x};{vers};{y}c
--- 4109,4120 ----
  	    /* URXVT mouse uses <ESC>[#;#;#M, but we are matching <ESC>[ */
  	    || key_name[0] == KS_URXVT_MOUSE
  # ifdef FEAT_MBYTE
  	    || u7_status == U7_SENT
  # endif
! 	    || focus_mode
! 	    )
  	{
  	    /* Check for some responses from terminal start with "<Esc>[" or
  	     * CSI.
  	     *
  	     * - xterm version string: <Esc>[>{x};{vers};{y}c
*************** check_termcode(max_offset, buf, bufsize,
*** 4113,4140 ****
  	     *   the escape sequence ends with a letter or one of "{|}~".
  	     *
  	     * - cursor position report: <Esc>[{row};{col}R
  	     *   The final byte is 'R'. now it is only used for checking for
  	     *   ambiguous-width character state.
  	     */
! 	    if ((*T_CRV != NUL || *T_U7 != NUL)
  			&& ((tp[0] == ESC && tp[1] == '[' && len >= 3)
  			    || (tp[0] == CSI && len >= 2)))
  	    {
  		j = 0;
  		extra = 0;
! 		for (i = 2 + (tp[0] != CSI); i < len
! 				&& !(tp[i] >= '{' && tp[i] <= '~')
! 				&& !ASCII_ISALPHA(tp[i]); ++i)
  		    if (tp[i] == ';' && ++j == 1)
  			extra = atoi((char *)tp + i + 1);
  		if (i == len)
  		    return -1;		/* not enough characters */
  
  #ifdef FEAT_MBYTE
  		/* eat it when it has 2 arguments and ends in 'R' */
! 		if (j == 1 && tp[i] == 'R')
  		{
  		    char *aw = NULL;
  
  		    u7_status = U7_GOT;
  # ifdef FEAT_AUTOCMD
--- 4124,4158 ----
  	     *   the escape sequence ends with a letter or one of "{|}~".
  	     *
  	     * - cursor position report: <Esc>[{row};{col}R
  	     *   The final byte is 'R'. now it is only used for checking for
  	     *   ambiguous-width character state.
+ 	     *
+ 	     * - focus report: <Esc>[I / <Esc>[O
+ 	     *   Xterm sends <Esc>[I (focus in event) or <Esc>[O (focus out event)
+ 	     *   when the private mode 1004 is enabled.
  	     */
! 	    if ((*T_CRV != NUL || *T_U7 != NUL || focus_mode)
  			&& ((tp[0] == ESC && tp[1] == '[' && len >= 3)
  			    || (tp[0] == CSI && len >= 2)))
  	    {
  		j = 0;
  		extra = 0;
! 		for (i = 1 + (tp[0] != CSI); i < len; ++i)
! 		{
! 		    /* Final byte of ECMA-48 control sequence (04/00-07/15) */
! 		    if (tp[i] >= '@' && tp[i] <= '~')
! 			break;
  		    if (tp[i] == ';' && ++j == 1)
  			extra = atoi((char *)tp + i + 1);
+ 		}
  		if (i == len)
  		    return -1;		/* not enough characters */
  
  #ifdef FEAT_MBYTE
  		/* eat it when it has 2 arguments and ends in 'R' */
! 		if (u7_status == U7_SENT && j == 1 && tp[i] == 'R')
  		{
  		    char *aw = NULL;
  
  		    u7_status = U7_GOT;
  # ifdef FEAT_AUTOCMD
*************** check_termcode(max_offset, buf, bufsize,
*** 4151,4161 ****
  		    slen = i + 1;
  		}
  		else
  #endif
  		/* eat it when at least one digit and ending in 'c' */
! 		if (*T_CRV != NUL && i > 2 + (tp[0] != CSI) && tp[i] == 'c')
  		{
  		    crv_status = CRV_GOT;
  # ifdef FEAT_AUTOCMD
  		    did_cursorhold = TRUE;
  # endif
--- 4169,4179 ----
  		    slen = i + 1;
  		}
  		else
  #endif
  		/* eat it when at least one digit and ending in 'c' */
! 		if (crv_status == CRV_SENT && i > 2 + (tp[0] != CSI) && tp[i] == 'c')
  		{
  		    crv_status = CRV_GOT;
  # ifdef FEAT_AUTOCMD
  		    did_cursorhold = TRUE;
  # endif
*************** check_termcode(max_offset, buf, bufsize,
*** 4206,4215 ****
--- 4224,4254 ----
  # endif
  		    key_name[0] = (int)KS_EXTRA;
  		    key_name[1] = (int)KE_IGNORE;
  		    slen = i + 1;
  		}
+ # ifdef FEAT_AUTOCMD
+ 		else if (focus_mode && j == 0)
+ 		{
+ 		    if (tp[i] == 'I')
+ 		    {
+ 			apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, FALSE, curbuf);
+ 			did_cursorhold = TRUE;
+ 			key_name[0] = (int)KS_EXTRA;
+ 			key_name[1] = (int)KE_IGNORE;
+ 			slen = 2 + (tp[0] != CSI);
+ 		    }
+ 		    else if (tp[i] == 'O')
+ 		    {
+ 			apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, FALSE, curbuf);
+ 			did_cursorhold = TRUE;
+ 			key_name[0] = (int)KS_EXTRA;
+ 			key_name[1] = (int)KE_IGNORE;
+ 			slen = 2 + (tp[0] != CSI);
+ 		    }
+ 		}
+ # endif
  	    }
  
  	    /* Check for '<Esc>P1+r<hex bytes><Esc>\'.  A "0" instead of the
  	     * "1" means an invalid request. */
  	    else if (check_for_codes
