diff options
author | Luuk van Baal <luukvbaal@gmail.com> | 2023-03-08 12:36:03 +0100 |
---|---|---|
committer | Luuk van Baal <luukvbaal@gmail.com> | 2023-03-08 12:36:03 +0100 |
commit | fe11079721084b3638ae3d8e5266f95d52028fb7 (patch) | |
tree | e7f749d6c7711dd46bbb698815167b7d1c92d7fa | |
parent | 1fb585a9db32ddfa563328a4ffb18b6f1e1dec1e (diff) | |
download | rneovim-fe11079721084b3638ae3d8e5266f95d52028fb7.tar.gz rneovim-fe11079721084b3638ae3d8e5266f95d52028fb7.tar.bz2 rneovim-fe11079721084b3638ae3d8e5266f95d52028fb7.zip |
perf(statusline): UI elements are always redrawn on K_EVENT
Problem: 'statusline'-format UI elements are redrawn on each K_EVENT.
Solution: Only redraw UI elements when something relevant has changed.
-rw-r--r-- | src/nvim/buffer_defs.h | 15 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 64 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 3 | ||||
-rw-r--r-- | src/nvim/option.c | 10 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 2 | ||||
-rw-r--r-- | src/nvim/screen.c | 2 | ||||
-rw-r--r-- | src/nvim/statusline.c | 224 |
7 files changed, 168 insertions, 152 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 05901893b9..6122136a75 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1279,13 +1279,14 @@ struct window_S { bool w_redr_border; // if true border 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) - pos_T w_ru_cursor; // cursor position shown in ruler - colnr_T w_ru_virtcol; // virtcol shown in ruler - linenr_T w_ru_topline; // topline shown in ruler - linenr_T w_ru_line_count; // line count used for ruler - int w_ru_topfill; // topfill shown in ruler - char w_ru_empty; // true if ruler shows 0-1 (empty line) + // remember what is shown in the 'statusline'-format elements + pos_T w_stl_cursor; // cursor position when last redrawn + colnr_T w_stl_virtcol; // virtcol when last redrawn + linenr_T w_stl_topline; // topline when last redrawn + linenr_T w_stl_line_count; // line count when last redrawn + int w_stl_topfill; // topfill when last redrawn + 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-^) diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 0ac5220599..384dbf82f9 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -92,6 +92,7 @@ #include "nvim/profile.h" #include "nvim/regexp.h" #include "nvim/screen.h" +#include "nvim/state.h" #include "nvim/statusline.h" #include "nvim/syntax.h" #include "nvim/terminal.h" @@ -733,28 +734,53 @@ void show_cursor_info(bool always) return; } - win_check_ns_hl(curwin); - if ((*p_stl != NUL || *curwin->w_p_stl != NUL) - && (curwin->w_status_height || global_stl_height())) { - redraw_custom_statusline(curwin); - } else { - win_redr_ruler(curwin, always); - } - if (*p_wbr != NUL || *curwin->w_p_wbr != NUL) { - win_redr_winbar(curwin); - } + 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); + if ((*p_stl != NUL || *curwin->w_p_stl != NUL) + && (curwin->w_status_height || global_stl_height())) { + redraw_custom_statusline(curwin); + } else { + win_redr_ruler(curwin); + } + if (*p_wbr != NUL || *curwin->w_p_wbr != NUL) { + win_redr_winbar(curwin); + } - if (need_maketitle - || (p_icon && (stl_syntax & STL_IN_ICON)) - || (p_title && (stl_syntax & STL_IN_TITLE))) { - maketitle(); - } + if (need_maketitle + || (p_icon && (stl_syntax & STL_IN_ICON)) + || (p_title && (stl_syntax & STL_IN_TITLE))) { + maketitle(); + } - win_check_ns_hl(NULL); - // Redraw the tab pages line if needed. - if (redraw_tabline) { - draw_tabline(); + win_check_ns_hl(NULL); + // Redraw the tab pages line if needed. + if (redraw_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) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index e4cb7a5a76..54131986d0 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -907,6 +907,9 @@ theend: ui_call_cmdline_hide(ccline.level); msg_ext_clear_later(); } + if (!cmd_silent) { + status_redraw_all(); // redraw to show mode change + } cmdline_level--; diff --git a/src/nvim/option.c b/src/nvim/option.c index 5ad2929a91..4e0fbc20f8 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -92,6 +92,7 @@ #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" +#include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/tag.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), BOOLEAN_OBJ(*varp)); } - - comp_col(); // in case 'ruler' or 'showcmd' changed + if ((int *)varp == &p_ru || (int *)varp == &p_sc) { + // in case 'ruler' or 'showcmd' changed + comp_col(); + if ((int *)varp == &p_ru) { + win_redr_ruler(curwin); + } + } if (curwin->w_curswant != MAXCOL && (options[opt_idx].flags & (P_CURSWANT | P_RALL)) != 0) { curwin->w_set_curswant = true; diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index b335e255a4..0774baf2d8 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -49,6 +49,7 @@ #include "nvim/spell.h" #include "nvim/spellfile.h" #include "nvim/spellsuggest.h" +#include "nvim/statusline.h" #include "nvim/strings.h" #include "nvim/tag.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) { comp_col(); + win_redr_ruler(curwin); } // add / remove window bars for 'winbar' if (gvarp == &p_wbr) { diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 61594860d2..43c7866180 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -611,7 +611,7 @@ int showmode(void) // the ruler is after the mode message and must be redrawn win_T *last = lastwin_nofloating(); if (redrawing() && last->w_status_height == 0 && global_stl_height() == 0) { - win_redr_ruler(last, true); + win_redr_ruler(last); } redraw_cmdline = false; diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index de91bf334c..ff03017e6c 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -162,7 +162,7 @@ void win_redr_status(win_T *wp) (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". if (p_sc && *p_sloc == 's') { @@ -443,7 +443,7 @@ void win_redr_winbar(win_T *wp) 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; static bool did_show_ext_ruler = false; @@ -473,138 +473,116 @@ void win_redr_ruler(win_T *wp, bool always) } // Check if not in Insert mode and the line is empty (will show "0-1"). - int empty_line = false; - if ((State & MODE_INSERT) == 0 && *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum, false) == NUL) { - empty_line = true; - } + int empty_line = (State & MODE_INSERT) == 0 + && *ml_get_buf(curwin->w_buffer, curwin->w_cursor.lnum, false) == NUL; - // 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 row; - int fillchar; - int attr; - int off; - bool part_of_status = false; - - if (wp->w_status_height) { - row = W_ENDROW(wp); - fillchar = fillchar_status(&attr, wp); - off = wp->w_wincol; - width = wp->w_width; - part_of_status = true; - } else if (is_stl_global) { - row = Rows - (int)p_ch - 1; - fillchar = fillchar_status(&attr, wp); - off = 0; - width = Columns; - part_of_status = true; - } else { - row = Rows - 1; - fillchar = ' '; - attr = HL_ATTR(HLF_MSG); - width = Columns; - off = 0; - } + int width; + int row; + int fillchar; + int attr; + int off; + bool part_of_status = false; - if (!part_of_status && p_ch == 0 && !ui_has(kUIMessages)) { - return; - } + if (wp->w_status_height) { + row = W_ENDROW(wp); + fillchar = fillchar_status(&attr, wp); + off = wp->w_wincol; + width = wp->w_width; + part_of_status = true; + } else if (is_stl_global) { + row = Rows - (int)p_ch - 1; + fillchar = fillchar_status(&attr, wp); + off = 0; + width = Columns; + part_of_status = true; + } else { + row = Rows - 1; + fillchar = ' '; + attr = HL_ATTR(HLF_MSG); + width = Columns; + off = 0; + } - // In list mode virtcol needs to be recomputed - colnr_T virtcol = wp->w_virtcol; - if (wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL) { - wp->w_p_list = false; - getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL); - wp->w_p_list = true; - } + if (!part_of_status && p_ch == 0 && !ui_has(kUIMessages)) { + return; + } + + // In list mode virtcol needs to be recomputed + colnr_T virtcol = wp->w_virtcol; + if (wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL) { + wp->w_p_list = false; + getvvcol(wp, &wp->w_cursor, NULL, &virtcol, NULL); + wp->w_p_list = true; + } #define RULER_BUF_LEN 70 - char buffer[RULER_BUF_LEN]; - - // Some sprintfs return the length, some return a pointer. - // To avoid portability problems we use strlen() here. - vim_snprintf(buffer, RULER_BUF_LEN, "%" PRId64 ",", - (wp->w_buffer->b_ml.ml_flags & - ML_EMPTY) ? (int64_t)0L : (int64_t)wp->w_cursor.lnum); - size_t len = strlen(buffer); - col_print(buffer + len, RULER_BUF_LEN - len, - empty_line ? 0 : (int)wp->w_cursor.col + 1, - (int)virtcol + 1); - - // Add a "50%" if there is room for it. - // On the last line, don't print in the last column (scrolls the - // screen up on some terminals). - int i = (int)strlen(buffer); - get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1); - int o = i + vim_strsize(buffer + i + 1); - if (wp->w_status_height == 0 && !is_stl_global) { // can't use last char of screen + char buffer[RULER_BUF_LEN]; + + // Some sprintfs return the length, some return a pointer. + // To avoid portability problems we use strlen() here. + vim_snprintf(buffer, RULER_BUF_LEN, "%" PRId64 ",", + (wp->w_buffer->b_ml.ml_flags & + ML_EMPTY) ? (int64_t)0L : (int64_t)wp->w_cursor.lnum); + size_t len = strlen(buffer); + col_print(buffer + len, RULER_BUF_LEN - len, + empty_line ? 0 : (int)wp->w_cursor.col + 1, + (int)virtcol + 1); + + // Add a "50%" if there is room for it. + // On the last line, don't print in the last column (scrolls the + // screen up on some terminals). + int i = (int)strlen(buffer); + get_rel_pos(wp, buffer + i + 1, RULER_BUF_LEN - i - 1); + int o = i + vim_strsize(buffer + i + 1); + if (wp->w_status_height == 0 && !is_stl_global) { // can't use last char of screen + o++; + } + int this_ru_col = ru_col - (Columns - width); + if (this_ru_col < 0) { + this_ru_col = 0; + } + // Never use more than half the window/screen width, leave the other half + // for the filename. + if (this_ru_col < (width + 1) / 2) { + this_ru_col = (width + 1) / 2; + } + if (this_ru_col + o < width) { + // Need at least 3 chars left for get_rel_pos() + NUL. + while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) { + i += utf_char2bytes(fillchar, buffer + i); o++; } - int this_ru_col = ru_col - (Columns - width); - if (this_ru_col < 0) { - this_ru_col = 0; - } - // Never use more than half the window/screen width, leave the other half - // for the filename. - if (this_ru_col < (width + 1) / 2) { - this_ru_col = (width + 1) / 2; - } - if (this_ru_col + o < width) { - // Need at least 3 chars left for get_rel_pos() + NUL. - while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) { - i += utf_char2bytes(fillchar, buffer + i); - o++; - } - get_rel_pos(wp, buffer + i, RULER_BUF_LEN - i); - } + get_rel_pos(wp, buffer + i, RULER_BUF_LEN - i); + } - if (ui_has(kUIMessages) && !part_of_status) { - MAXSIZE_TEMP_ARRAY(content, 1); - MAXSIZE_TEMP_ARRAY(chunk, 2); - ADD_C(chunk, INTEGER_OBJ(attr)); - ADD_C(chunk, STRING_OBJ(cstr_as_string(buffer))); - ADD_C(content, ARRAY_OBJ(chunk)); - ui_call_msg_ruler(content); - did_show_ext_ruler = true; - } else { - if (did_show_ext_ruler) { - ui_call_msg_ruler((Array)ARRAY_DICT_INIT); - did_show_ext_ruler = false; - } - // Truncate at window boundary. - o = 0; - for (i = 0; buffer[i] != NUL; i += utfc_ptr2len(buffer + i)) { - o += utf_ptr2cells(buffer + i); - if (this_ru_col + o > width) { - buffer[i] = NUL; - break; - } + if (ui_has(kUIMessages) && !part_of_status) { + MAXSIZE_TEMP_ARRAY(content, 1); + MAXSIZE_TEMP_ARRAY(chunk, 2); + ADD_C(chunk, INTEGER_OBJ(attr)); + ADD_C(chunk, STRING_OBJ(cstr_as_string(buffer))); + ADD_C(content, ARRAY_OBJ(chunk)); + ui_call_msg_ruler(content); + did_show_ext_ruler = true; + } else { + if (did_show_ext_ruler) { + ui_call_msg_ruler((Array)ARRAY_DICT_INIT); + did_show_ext_ruler = false; + } + // Truncate at window boundary. + o = 0; + for (i = 0; buffer[i] != NUL; i += utfc_ptr2len(buffer + i)) { + o += utf_ptr2cells(buffer + i); + if (this_ru_col + o > width) { + buffer[i] = NUL; + break; } - - ScreenGrid *grid = part_of_status ? &default_grid : &msg_grid_adj; - grid_puts(grid, buffer, row, this_ru_col + off, attr); - grid_fill(grid, row, row + 1, - this_ru_col + off + (int)strlen(buffer), off + width, fillchar, - 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; + ScreenGrid *grid = part_of_status ? &default_grid : &msg_grid_adj; + grid_puts(grid, buffer, row, this_ru_col + off, attr); + grid_fill(grid, row, row + 1, + this_ru_col + off + (int)strlen(buffer), off + width, fillchar, + fillchar, attr); } } |