Bram,
I am maintaining a eye-candy statusline plugin, that can also create a 
nice tabline. I recently made a change, trying to improve the 
performance of the plugin by caching certain values 
(https://github.com/vim-airline/vim-airline/commit/b2f301f73c168104cf2202ac5f2e2b7c078c7aa1)

The issue can be reproduced with this little vim snippet:
,----
| function! TabTitle(n)
|  let title = gettabvar(a:n, 'title')
|  if empty(title)
|     " call an expensive function to get the title
|     " try to avoid the expensive call, by caching the title
|     let title='foobar'
|  endif
|  "if a:n == tabpagenr()
|  "   let t:title = title
|  "endif
|  call settabvar(a:n, 'title', title)
|  return title
| endfunction
| 
| function! DrawTabline()
|  let tabline = ''
|  for i in range(1, tabpagenr('$'))
|      let tabline .= "%(Tab: ".i.' "%{TabTitle('.i.')}"%)'
|  endfor
|  return tabline
| endfunction
| set tabline=%!DrawTabline()
`----


However, it turns out, that this causes flicker on movement and so makes 
Vim redraw a lot more often than actually needed. I looked into the 
source, trying to find out, why this happens and I think it happens 
because settabvar does internally switch tabpages (e.g. calling 
enter_tabpage) which unconditionally set must_redraw=CLEAR.

However this happens on a call to draw_tabline() which is done when we 
already updating the screen (e.g. in a callchain coming from 
update_scree()). So I think we can prevent this by only setting 
must_redraw, if we are not updating the screen currently, which is what 
this patch does:

diff --git a/src/window.c b/src/window.c
index 8078e011d..785d240e8 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3925,7 +3925,8 @@ enter_tabpage(

     last_status(FALSE);                /* status line may appear or disappear 
*/
     (void)win_comp_pos();      /* recompute w_winrow for all windows */
-    must_redraw = CLEAR;       /* need to redraw everything */
+    if (!updating_screen)
+       must_redraw = CLEAR;    /* need to redraw everything */
 #ifdef FEAT_DIFF
     diff_need_scrollbind = TRUE;
 #endif

On a second thought, it might be better not to set must_redraw for 
settabvar() at all, since after we are finished, we switch back the 
tabpage, and thus theoretically a redraw should not be necessary. So 
perhaps this patch is preferable:

diff --git a/src/evalfunc.c b/src/evalfunc.c
index 2d796f7e1..4b8f95e50 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -10385,6 +10385,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv)
 #endif
     char_u     *varname, *tabvarname;
     typval_T   *varp;
+    int         redraw;

     rettv->vval.v_number = 0;

@@ -10404,6 +10405,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv)
            )
     {
 #ifdef FEAT_WINDOWS
+       redraw = must_redraw;
        save_curtab = curtab;
        goto_tabpage_tp(tp, FALSE, FALSE);
 #endif
@@ -10421,6 +10423,7 @@ f_settabvar(typval_T *argvars, typval_T *rettv)
        /* Restore current tabpage */
        if (valid_tabpage(save_curtab))
            goto_tabpage_tp(save_curtab, FALSE, FALSE);
+       must_redraw = redraw; /* avoid an unnecessary redraw */
 #endif
     }
 }


And finally, I made another observation, that looks suspicious as well. 
When update_screen() is called, it will eventually call this code, if 
type==CLEAR:
,----
|      if (type == CLEAR)          /* first clear screen */
|       {
|           screenclear();          /* will reset clear_cmdline */
|           type = NOT_VALID;
|       }
`----

screenclear() will then call screenclear2() which will call 
win_rest_invalid(firstwin)
which will then call
,----
|           redraw_win_later(wp, NOT_VALID);
`----

So although we are in the process of updating the current screen, we 
will force another redraw after the next main_loop. I think we can save 
that call here, and only call redraw_win_later if updating_screen is not 
true. 

Best,
Christian
-- 
Moral ist eine Wichtigtuerei des Menschen vor der Natur.
                -- Friedrich Wilhelm Nietzsche

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui