aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2022-08-17 15:40:21 +0200
committerbfredl <bjorn.linse@gmail.com>2022-09-22 10:38:10 +0200
commit93b30582db520ae20d66b000053007c11b62c15d (patch)
treef1f3f829a263927047055216dcd259e2e51b9186
parent00cfc1dcebd1c81dd0d8c111740782e86cf2e385 (diff)
downloadrneovim-93b30582db520ae20d66b000053007c11b62c15d.tar.gz
rneovim-93b30582db520ae20d66b000053007c11b62c15d.tar.bz2
rneovim-93b30582db520ae20d66b000053007c11b62c15d.zip
fix(redraw): make redrawdebug=nodelta handle all the cases
Before only win_line lines were considered. this applies nodelta to all screen elements. Causes some failures, which might indeed indicate excessive redraws.
-rw-r--r--src/nvim/decoration.c5
-rw-r--r--src/nvim/drawline.c1
-rw-r--r--src/nvim/drawscreen.c32
-rw-r--r--src/nvim/grid.c11
-rw-r--r--src/nvim/screen.c2
-rw-r--r--src/nvim/sign.c6
-rw-r--r--test/functional/ui/syntax_conceal_spec.lua7
7 files changed, 43 insertions, 21 deletions
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 778f9293fb..5a1708a57c 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -75,12 +75,11 @@ void decor_redraw(buf_T *buf, int row1, int row2, Decoration *decor)
}
if (decor && decor_virt_pos(*decor)) {
- redraw_buf_line_later(buf, row1 + 1);
+ redraw_buf_line_later(buf, row1 + 1, false);
}
if (decor && kv_size(decor->virt_lines)) {
- redraw_buf_line_later(buf, MIN(buf->b_ml.ml_line_count,
- row1 + 1 + (decor->virt_lines_above?0:1)));
+ redraw_buf_line_later(buf, row1 + 1 + (decor->virt_lines_above?0:1), true);
}
}
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index 25ea2e1000..5c3fa3d3b0 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -2638,6 +2638,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
// When the window is too narrow draw all "@" lines.
if (draw_state != WL_LINE && filler_todo <= 0) {
win_draw_end(wp, '@', ' ', true, row, wp->w_grid.rows, HLF_AT);
+ set_empty_rows(wp, row);
row = endrow;
}
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index fb98e3effc..c95f3f3550 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -1018,6 +1018,9 @@ win_update_start:
bool scrolled_down = false; // true when scrolled down when w_topline got smaller a bit
bool top_to_mod = false; // redraw above mod_top
+ int bot_scroll_start = 999; // first line that needs to be redrawn due to
+ // scrolling. only used for EOB
+
int row; // current window row to display
linenr_T lnum; // current buffer lnum to display
int idx; // current index in w_lines[]
@@ -1195,6 +1198,7 @@ win_update_start:
mod_bot = MAXLNUM;
}
}
+
wp->w_redraw_top = 0; // reset for next time
wp->w_redraw_bot = 0;
@@ -1265,6 +1269,7 @@ win_update_start:
// If not the last window, delete the lines at the bottom.
// win_ins_lines may fail when the terminal can't do it.
win_scroll_lines(wp, 0, i);
+ bot_scroll_start = 0;
if (wp->w_lines_valid != 0) {
// Need to update rows that are new, stop at the
// first one that scrolled down.
@@ -1325,6 +1330,7 @@ win_update_start:
if (row > 0) {
win_scroll_lines(wp, 0, -row);
bot_start = wp->w_grid.rows - row;
+ bot_scroll_start = bot_start;
}
if ((row == 0 || bot_start < 999) && wp->w_lines_valid != 0) {
// Skip the lines (below the deleted lines) that are still
@@ -1702,6 +1708,7 @@ win_update_start:
// need to redraw until the end of the window.
// Inserting/deleting lines has no use.
bot_start = 0;
+ bot_scroll_start = 0;
} else {
// Able to count old number of rows: Count new window
// rows, and may insert/delete lines
@@ -1732,6 +1739,7 @@ win_update_start:
} else {
win_scroll_lines(wp, row, xtra_rows);
bot_start = wp->w_grid.rows + xtra_rows;
+ bot_scroll_start = bot_start;
}
} else if (xtra_rows > 0) {
// May scroll text down. If there is not enough
@@ -1741,6 +1749,7 @@ win_update_start:
mod_bot = MAXLNUM;
} else {
win_scroll_lines(wp, row + old_rows, xtra_rows);
+ bot_scroll_start = 0;
if (top_end > row + old_rows) {
// Scrolled the part at the top that requires
// updating down.
@@ -1930,6 +1939,7 @@ win_update_start:
wp->w_botline = lnum;
} else {
win_draw_end(wp, '@', ' ', true, srow, wp->w_grid.rows, HLF_AT);
+ set_empty_rows(wp, srow);
wp->w_botline = lnum;
}
} else {
@@ -1950,8 +1960,18 @@ win_update_start:
// Make sure the rest of the screen is blank.
// write the "eob" character from 'fillchars' to rows that aren't part
// of the file.
- win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, row, wp->w_grid.rows,
+ // TODO(bfredl): just keep track of the valid EOB area from last redraw?
+ int lastline = bot_scroll_start;
+ if (mid_end >= row) {
+ lastline = MIN(lastline, mid_start);
+ }
+ if (mod_bot > buf->b_ml.ml_line_count + 1) {
+ lastline = 0;
+ }
+
+ win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, MAX(lastline, row), wp->w_grid.rows,
HLF_EOB);
+ set_empty_rows(wp, row);
}
kvi_destroy(line_providers);
@@ -2063,12 +2083,14 @@ void redraw_buf_later(buf_T *buf, int type)
}
}
-void redraw_buf_line_later(buf_T *buf, linenr_T line)
+void redraw_buf_line_later(buf_T *buf, linenr_T line, bool force)
{
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf
- && line >= wp->w_topline && line < wp->w_botline) {
- redrawWinline(wp, line);
+ if (wp->w_buffer == buf) {
+ redrawWinline(wp, MIN(line, buf->b_ml.ml_line_count));
+ if (force && line > buf->b_ml.ml_line_count) {
+ wp->w_redraw_bot = line;
+ }
}
}
}
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index 63bb945f73..2b73ff895d 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -175,7 +175,7 @@ void grid_put_schar(ScreenGrid *grid, int row, int col, char *schar, int attr)
{
assert(put_dirty_row == row);
size_t off = grid->line_offset[row] + (size_t)col;
- if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar)) {
+ if (grid->attrs[off] != attr || schar_cmp(grid->chars[off], schar) || rdb_flags & RDB_NODELTA) {
schar_copy(grid->chars[off], schar);
grid->attrs[off] = attr;
@@ -280,7 +280,8 @@ void grid_puts_len(ScreenGrid *grid, char *text, int textlen, int row, int col,
need_redraw = schar_cmp(grid->chars[off], buf)
|| (mbyte_cells == 2 && grid->chars[off + 1][0] != 0)
|| grid->attrs[off] != attr
- || exmode_active;
+ || exmode_active
+ || rdb_flags & RDB_NODELTA;
if (need_redraw) {
// When at the end of the text and overwriting a two-cell
@@ -412,8 +413,7 @@ void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int
size_t lineoff = grid->line_offset[row];
for (col = start_col; col < end_col; col++) {
size_t off = lineoff + (size_t)col;
- if (schar_cmp(grid->chars[off], sc)
- || grid->attrs[off] != attr) {
+ if (schar_cmp(grid->chars[off], sc) || grid->attrs[off] != attr || rdb_flags & RDB_NODELTA) {
schar_copy(grid->chars[off], sc);
grid->attrs[off] = attr;
if (dirty_first == INT_MAX) {
@@ -605,7 +605,8 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int endcol, int cle
while (col < clear_width) {
if (grid->chars[off_to][0] != ' '
|| grid->chars[off_to][1] != NUL
- || grid->attrs[off_to] != bg_attr) {
+ || grid->attrs[off_to] != bg_attr
+ || rdb_flags & RDB_NODELTA) {
grid->chars[off_to][0] = ' ';
grid->chars[off_to][1] = NUL;
grid->attrs[off_to] = bg_attr;
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index cdfb1e9ee1..1af93f061c 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -155,8 +155,6 @@ void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endr
} else {
grid_fill(&wp->w_grid, row, endrow, n, wp->w_grid.cols, c1, c2, attr);
}
-
- set_empty_rows(wp, row);
}
/// Compute the width of the foldcolumn. Based on 'foldcolumn' and how much
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index 5ce9ee4546..6f13dd2f06 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -557,7 +557,7 @@ static linenr_T buf_delsign(buf_T *buf, linenr_T atlnum, int id, char *group)
sign_group_unref((char *)sign->se_group->sg_name);
}
xfree(sign);
- redraw_buf_line_later(buf, lnum);
+ redraw_buf_line_later(buf, lnum, false);
// Check whether only one sign needs to be deleted
// If deleting a sign with a specific identifier in a particular
// group or deleting any sign at a particular line number, delete
@@ -1062,7 +1062,7 @@ static int sign_place(int *sign_id, const char *sign_group, const char *sign_nam
lnum = buf_change_sign_type(buf, *sign_id, (char *)sign_group, sp->sn_typenr, prio);
}
if (lnum > 0) {
- redraw_buf_line_later(buf, lnum);
+ redraw_buf_line_later(buf, lnum, false);
// When displaying signs in the 'number' column, if the width of the
// number column is less than 2, then force recomputing the width.
@@ -1093,7 +1093,7 @@ static int sign_unplace(int sign_id, char *sign_group, buf_T *buf, linenr_T atln
if (lnum == 0) {
return FAIL;
}
- redraw_buf_line_later(buf, lnum);
+ redraw_buf_line_later(buf, lnum, false);
}
// When all the signs in a buffer are removed, force recomputing the
diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua
index f790597140..e8798ddd93 100644
--- a/test/functional/ui/syntax_conceal_spec.lua
+++ b/test/functional/ui/syntax_conceal_spec.lua
@@ -947,7 +947,7 @@ describe('Screen', function()
{0:~ }|
|
]]}
- eq({{2, 0, {{'c', 0, 3}}}}, grid_lines)
+ eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}, {3, 0, {{' ', 0, 53}}}}, grid_lines)
end)
it('K_EVENT should not cause extra redraws with concealcursor #13196', function()
@@ -994,10 +994,11 @@ describe('Screen', function()
{0:~ }|
|
]]}
- eq({{2, 0, {{'c', 0, 3}}}}, grid_lines)
+ eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}}, grid_lines)
+ grid_lines = {}
poke_eventloop() -- causes K_EVENT key
screen:expect_unchanged()
- eq({{2, 0, {{'c', 0, 3}}}}, grid_lines)
+ eq({}, grid_lines) -- no redraw was done
end)
-- Copy of Test_cursor_column_in_concealed_line_after_window_scroll in