Merge pull request #22547 from luukvbaal/statusline

perf(statusline): UI elements are always redrawn on K_EVENT
This commit is contained in:
bfredl 2023-03-09 11:06:47 +01:00 committed by GitHub
commit 46d4d420e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 200 additions and 151 deletions

View File

@ -1279,13 +1279,14 @@ struct window_S {
bool w_redr_border; // if true border must be redrawn bool w_redr_border; // if true border must be redrawn
bool w_redr_statuscol; // if true 'statuscolumn' must be redrawn bool w_redr_statuscol; // if true 'statuscolumn' must be redrawn
// remember what is shown in the ruler for this window (if 'ruler' set) // remember what is shown in the 'statusline'-format elements
pos_T w_ru_cursor; // cursor position shown in ruler pos_T w_stl_cursor; // cursor position when last redrawn
colnr_T w_ru_virtcol; // virtcol shown in ruler colnr_T w_stl_virtcol; // virtcol when last redrawn
linenr_T w_ru_topline; // topline shown in ruler linenr_T w_stl_topline; // topline when last redrawn
linenr_T w_ru_line_count; // line count used for ruler linenr_T w_stl_line_count; // line count when last redrawn
int w_ru_topfill; // topfill shown in ruler int w_stl_topfill; // topfill when last redrawn
char w_ru_empty; // true if ruler shows 0-1 (empty line) char w_stl_empty; // true if elements show 0-1 (empty line)
int w_stl_state; // State when last redrawn
int w_alt_fnum; // alternate file (for # and CTRL-^) int w_alt_fnum; // alternate file (for # and CTRL-^)

View File

@ -92,6 +92,7 @@
#include "nvim/profile.h" #include "nvim/profile.h"
#include "nvim/regexp.h" #include "nvim/regexp.h"
#include "nvim/screen.h" #include "nvim/screen.h"
#include "nvim/state.h"
#include "nvim/statusline.h" #include "nvim/statusline.h"
#include "nvim/syntax.h" #include "nvim/syntax.h"
#include "nvim/terminal.h" #include "nvim/terminal.h"
@ -733,12 +734,28 @@ void show_cursor_info(bool always)
return; return;
} }
int state = get_real_state();
int empty_line = (State & MODE_INSERT) == 0
&& *ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false) == NUL;
// Only draw when something changed.
validate_virtcol_win(curwin);
if (always
|| curwin->w_cursor.lnum != curwin->w_stl_cursor.lnum
|| curwin->w_cursor.col != curwin->w_stl_cursor.col
|| curwin->w_virtcol != curwin->w_stl_virtcol
|| curwin->w_cursor.coladd != curwin->w_stl_cursor.coladd
|| curwin->w_topline != curwin->w_stl_topline
|| curwin->w_buffer->b_ml.ml_line_count != curwin->w_stl_line_count
|| curwin->w_topfill != curwin->w_stl_topfill
|| empty_line != curwin->w_stl_empty
|| state != curwin->w_stl_state) {
win_check_ns_hl(curwin); win_check_ns_hl(curwin);
if ((*p_stl != NUL || *curwin->w_p_stl != NUL) if ((*p_stl != NUL || *curwin->w_p_stl != NUL)
&& (curwin->w_status_height || global_stl_height())) { && (curwin->w_status_height || global_stl_height())) {
redraw_custom_statusline(curwin); redraw_custom_statusline(curwin);
} else { } else {
win_redr_ruler(curwin, always); win_redr_ruler(curwin);
} }
if (*p_wbr != NUL || *curwin->w_p_wbr != NUL) { if (*p_wbr != NUL || *curwin->w_p_wbr != NUL) {
win_redr_winbar(curwin); win_redr_winbar(curwin);
@ -755,6 +772,15 @@ void show_cursor_info(bool always)
if (redraw_tabline) { if (redraw_tabline) {
draw_tabline(); draw_tabline();
} }
}
curwin->w_stl_cursor = curwin->w_cursor;
curwin->w_stl_virtcol = curwin->w_virtcol;
curwin->w_stl_empty = (char)empty_line;
curwin->w_stl_topline = curwin->w_topline;
curwin->w_stl_line_count = curwin->w_buffer->b_ml.ml_line_count;
curwin->w_stl_topfill = curwin->w_topfill;
curwin->w_stl_state = state;
} }
static void redraw_win_signcol(win_T *wp) static void redraw_win_signcol(win_T *wp)

View File

@ -907,6 +907,9 @@ theend:
ui_call_cmdline_hide(ccline.level); ui_call_cmdline_hide(ccline.level);
msg_ext_clear_later(); msg_ext_clear_later();
} }
if (!cmd_silent) {
status_redraw_all(); // redraw to show mode change
}
cmdline_level--; cmdline_level--;

View File

@ -92,6 +92,7 @@
#include "nvim/spell.h" #include "nvim/spell.h"
#include "nvim/spellfile.h" #include "nvim/spellfile.h"
#include "nvim/spellsuggest.h" #include "nvim/spellsuggest.h"
#include "nvim/statusline.h"
#include "nvim/strings.h" #include "nvim/strings.h"
#include "nvim/tag.h" #include "nvim/tag.h"
#include "nvim/terminal.h" #include "nvim/terminal.h"
@ -2251,8 +2252,13 @@ static char *set_bool_option(const int opt_idx, char *const varp, const int valu
ui_call_option_set(cstr_as_string(options[opt_idx].fullname), ui_call_option_set(cstr_as_string(options[opt_idx].fullname),
BOOLEAN_OBJ(*varp)); BOOLEAN_OBJ(*varp));
} }
if ((int *)varp == &p_ru || (int *)varp == &p_sc) {
comp_col(); // in case 'ruler' or 'showcmd' changed // in case 'ruler' or 'showcmd' changed
comp_col();
if ((int *)varp == &p_ru) {
win_redr_ruler(curwin);
}
}
if (curwin->w_curswant != MAXCOL if (curwin->w_curswant != MAXCOL
&& (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) { && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) {
curwin->w_set_curswant = true; curwin->w_set_curswant = true;

View File

@ -49,6 +49,7 @@
#include "nvim/spell.h" #include "nvim/spell.h"
#include "nvim/spellfile.h" #include "nvim/spellfile.h"
#include "nvim/spellsuggest.h" #include "nvim/spellsuggest.h"
#include "nvim/statusline.h"
#include "nvim/strings.h" #include "nvim/strings.h"
#include "nvim/tag.h" #include "nvim/tag.h"
#include "nvim/ui.h" #include "nvim/ui.h"
@ -1220,6 +1221,7 @@ static void did_set_statusline(win_T *win, char **varp, char **gvarp, char **err
} }
if (varp == &p_ruf && *errmsg == NULL) { if (varp == &p_ruf && *errmsg == NULL) {
comp_col(); comp_col();
win_redr_ruler(curwin);
} }
// add / remove window bars for 'winbar' // add / remove window bars for 'winbar'
if (gvarp == &p_wbr) { if (gvarp == &p_wbr) {

View File

@ -611,7 +611,7 @@ int showmode(void)
// the ruler is after the mode message and must be redrawn // the ruler is after the mode message and must be redrawn
win_T *last = lastwin_nofloating(); win_T *last = lastwin_nofloating();
if (redrawing() && last->w_status_height == 0 && global_stl_height() == 0) { if (redrawing() && last->w_status_height == 0 && global_stl_height() == 0) {
win_redr_ruler(last, true); win_redr_ruler(last);
} }
redraw_cmdline = false; redraw_cmdline = false;

View File

@ -162,7 +162,7 @@ void win_redr_status(win_T *wp)
(int)((size_t)this_ru_col - strlen(NameBuff) - 1), attr); (int)((size_t)this_ru_col - strlen(NameBuff) - 1), attr);
} }
win_redr_ruler(wp, true); win_redr_ruler(wp);
// Draw the 'showcmd' information if 'showcmdloc' == "statusline". // Draw the 'showcmd' information if 'showcmdloc' == "statusline".
if (p_sc && *p_sloc == 's') { if (p_sc && *p_sloc == 's') {
@ -443,7 +443,7 @@ void win_redr_winbar(win_T *wp)
entered = false; entered = false;
} }
void win_redr_ruler(win_T *wp, bool always) void win_redr_ruler(win_T *wp)
{ {
bool is_stl_global = global_stl_height() > 0; bool is_stl_global = global_stl_height() > 0;
static bool did_show_ext_ruler = false; static bool did_show_ext_ruler = false;
@ -473,23 +473,9 @@ void win_redr_ruler(win_T *wp, bool always)
} }
// Check if not in Insert mode and the line is empty (will show "0-1"). // Check if not in Insert mode and the line is empty (will show "0-1").
int empty_line = false; int empty_line = (State & MODE_INSERT) == 0
if ((State & MODE_INSERT) == 0 && *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, false) == NUL) { && *ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false) == NUL;
empty_line = true;
}
// Only draw the ruler when something changed.
validate_virtcol_win(wp);
if (redraw_cmdline
|| always
|| wp->w_cursor.lnum != wp->w_ru_cursor.lnum
|| wp->w_cursor.col != wp->w_ru_cursor.col
|| wp->w_virtcol != wp->w_ru_virtcol
|| wp->w_cursor.coladd != wp->w_ru_cursor.coladd
|| wp->w_topline != wp->w_ru_topline
|| wp->w_buffer->b_ml.ml_line_count != wp->w_ru_line_count
|| wp->w_topfill != wp->w_ru_topfill
|| empty_line != wp->w_ru_empty) {
int width; int width;
int row; int row;
int fillchar; int fillchar;
@ -598,14 +584,6 @@ void win_redr_ruler(win_T *wp, bool always)
this_ru_col + off + (int)strlen(buffer), off + width, fillchar, this_ru_col + off + (int)strlen(buffer), off + width, fillchar,
fillchar, attr); fillchar, attr);
} }
wp->w_ru_cursor = wp->w_cursor;
wp->w_ru_virtcol = wp->w_virtcol;
wp->w_ru_empty = (char)empty_line;
wp->w_ru_topline = wp->w_topline;
wp->w_ru_line_count = wp->w_buffer->b_ml.ml_line_count;
wp->w_ru_topfill = wp->w_topfill;
}
} }
/// Get the character to use in a status line. Get its attributes in "*attr". /// Get the character to use in a status line. Get its attributes in "*attr".

View File

@ -10,6 +10,7 @@ local meths = helpers.meths
local exec = helpers.exec local exec = helpers.exec
local exec_lua = helpers.exec_lua local exec_lua = helpers.exec_lua
local eval = helpers.eval local eval = helpers.eval
local sleep = helpers.sleep
describe('statusline clicks', function() describe('statusline clicks', function()
local screen local screen
@ -589,3 +590,35 @@ it('showcmdloc=statusline does not show if statusline is too narrow', function()
feed('1234') feed('1234')
screen:expect_unchanged() screen:expect_unchanged()
end) end)
it('K_EVENT does not trigger a statusline redraw unnecessarily', function()
clear()
local screen = Screen.new(40, 8)
screen:attach()
-- does not redraw on vim.schedule (#17937)
command([[
set laststatus=2
let g:counter = 0
func Status()
let g:counter += 1
lua vim.schedule(function() end)
return g:counter
endfunc
set statusline=%!Status()
]])
sleep(50)
eq(1, eval('g:counter < 50'), 'g:counter=' .. eval('g:counter'))
-- also in insert mode
feed('i')
sleep(50)
eq(1, eval('g:counter < 50'), 'g:counter=' .. eval('g:counter'))
-- does not redraw on timer call (#14303)
command([[
let g:counter = 0
func Timer(timer)
endfunc
call timer_start(1, 'Timer', {'repeat': 100})
]])
sleep(50)
eq(1, eval('g:counter < 50'), 'g:counter=' .. eval('g:counter'))
end)