aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2019-09-15 13:22:53 +0200
committerBjörn Linse <bjorn.linse@gmail.com>2019-09-15 15:30:48 +0200
commita0f13095aab7b791853e4509516568259706377d (patch)
treef0bed89ae7b7f3c157b48ba751c562ec4b0cf5af
parent86e819d492faa2494ffe0e86f37c49eb4c0f2e56 (diff)
downloadrneovim-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.c33
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) {