mirror of
https://github.com/neovim/neovim.git
synced 2025-10-08 10:56:31 +00:00
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).
This commit is contained in:
@@ -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) {
|
||||
|
Reference in New Issue
Block a user