aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2023-03-08 12:36:03 +0100
committerLuuk van Baal <luukvbaal@gmail.com>2023-03-08 12:36:03 +0100
commitfe11079721084b3638ae3d8e5266f95d52028fb7 (patch)
treee7f749d6c7711dd46bbb698815167b7d1c92d7fa
parent1fb585a9db32ddfa563328a4ffb18b6f1e1dec1e (diff)
downloadrneovim-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.h15
-rw-r--r--src/nvim/drawscreen.c64
-rw-r--r--src/nvim/ex_getln.c3
-rw-r--r--src/nvim/option.c10
-rw-r--r--src/nvim/optionstr.c2
-rw-r--r--src/nvim/screen.c2
-rw-r--r--src/nvim/statusline.c224
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);
}
}