diff options
author | Björn Linse <bjorn.linse@gmail.com> | 2019-09-15 13:22:53 +0200 |
---|---|---|
committer | Björn Linse <bjorn.linse@gmail.com> | 2019-09-15 15:30:48 +0200 |
commit | a0f13095aab7b791853e4509516568259706377d (patch) | |
tree | f0bed89ae7b7f3c157b48ba751c562ec4b0cf5af | |
parent | 86e819d492faa2494ffe0e86f37c49eb4c0f2e56 (diff) | |
download | rneovim-a0f13095aab7b791853e4509516568259706377d.tar.gz rneovim-a0f13095aab7b791853e4509516568259706377d.tar.bz2 rneovim-a0f13095aab7b791853e4509516568259706377d.zip |
compositor: avoid transmitting invalid lines on double scroll
This happens in an operation which both increases topline and also
inserts new lines somewhere in the remaining are. So before drawing any
line, win_update() is performing two grid_scroll operations.
===
A
B
C
D
E^
F
===
Consider that new line will be inserted after line E and screen also
scrolled up to line C. First the topline will be adjusted (x is the
scrolling region, ! invalid/empty space created by the scroll):
===
C x
D x
E^ x
F x
! x
! x
===
and then space is inserted for the new line
===
C
D
E^
! x
F x
! x
===
The problem is that we are now assuming that any invalid area ! created
by a scroll is filled with actual contents (by win_line etc) before it
is scrolled again. But in this case the last invalid line ! gets
scrolled. Ideally we should make win_update smarter and just scroll
valid lines for the later scroll (it is just wasteful to scroll the
larger area anyway), but for the 0.4 releasejust make
the compositor ignore such an invalid line (as it will get overdrawn
anyway later).
-rw-r--r-- | src/nvim/ui_compositor.c | 33 |
1 files changed, 23 insertions, 10 deletions
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c index 1af027d415..20ffc1b88e 100644 --- a/src/nvim/ui_compositor.c +++ b/src/nvim/ui_compositor.c @@ -526,9 +526,7 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row, endcol = MIN(endcol, clearcol); } - bool above_msg = (kv_A(layers, kv_size(layers)-1) == &msg_grid - && row < msg_current_row-(msg_was_scrolled?1:0)); - bool covered = kv_size(layers)-(above_msg?1:0) > curgrid->comp_index+1; + bool covered = curgrid_covered_above((int)row); // TODO(bfredl): eventually should just fix compose_line to respect clearing // and optimize it for uncovered lines. if (flags & kLineFlagInvalid || covered || curgrid->blending) { @@ -588,6 +586,16 @@ static void ui_comp_msg_set_pos(UI *ui, Integer grid, Integer row, msg_was_scrolled = scrolled; } +/// check if curgrid is covered on row or above +/// +/// TODO(bfredl): currently this only handles message row +static bool curgrid_covered_above(int row) +{ + bool above_msg = (kv_A(layers, kv_size(layers)-1) == &msg_grid + && row < msg_current_row-(msg_was_scrolled?1:0)); + return kv_size(layers)-(above_msg?1:0) > curgrid->comp_index+1; +} + static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left, Integer right, Integer rows, Integer cols) @@ -599,18 +607,23 @@ static void ui_comp_grid_scroll(UI *ui, Integer grid, Integer top, bot += curgrid->comp_row; left += curgrid->comp_col; right += curgrid->comp_col; - bool covered = kv_size(layers) > curgrid->comp_index+1 || curgrid->blending; + bool covered = curgrid_covered_above((int)(bot - MAX(rows, 0))); - if (covered) { + if (covered || curgrid->blending) { // TODO(bfredl): // 1. check if rectangles actually overlap // 2. calulate subareas that can scroll. - if (rows > 0) { - bot -= rows; - } else { - top += (-rows); + compose_debug(top, bot, left, right, dbghl_recompose, true); + for (int r = (int)(top + MAX(-rows, 0)); r < bot - MAX(rows, 0); r++) { + // TODO(bfredl): workaround for win_update() performing two scrolls in a + // row, where the latter might scroll invalid space created by the first. + // ideally win_update() should keep track of this itself and not scroll + // the invalid space. + if (curgrid->attrs[curgrid->line_offset[r-curgrid->comp_row] + +left-curgrid->comp_col] >= 0) { + compose_line(r, left, right, 0); + } } - compose_area(top, bot, left, right); } else { ui_composed_call_grid_scroll(1, top, bot, left, right, rows, cols); if (rdb_flags & RDB_COMPOSITOR) { |