perf(ui-ext): approximate scroll_delta when scrolling too much (#24234)

This commit is contained in:
zeertzjq 2023-07-04 16:48:53 +08:00 committed by GitHub
parent e8b3ed74bc
commit a76b689b47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 250 additions and 15 deletions

View File

@ -640,7 +640,8 @@ tabs.
the top line of a window moved since `win_viewport` was last emitted. the top line of a window moved since `win_viewport` was last emitted.
It is intended to be used to implement smooth scrolling. For this It is intended to be used to implement smooth scrolling. For this
purpose it only counts "virtual" or "displayed" lines, so folds purpose it only counts "virtual" or "displayed" lines, so folds
only count as one line. only count as one line. When scrolling more than a full screen it is
an approximate value.
["win_extmark", grid, win, ns_id, mark_id, row, col] ~ ["win_extmark", grid, win, ns_id, mark_id, row, col] ~
Updates the position of an extmark which is currently visible in a Updates the position of an extmark which is currently visible in a

View File

@ -1226,6 +1226,7 @@ struct window_S {
bool w_viewport_invalid; bool w_viewport_invalid;
linenr_T w_viewport_last_topline; // topline when the viewport was last updated linenr_T w_viewport_last_topline; // topline when the viewport was last updated
linenr_T w_viewport_last_botline; // botline when the viewport was last updated
linenr_T w_viewport_last_topfill; // topfill when the viewport was last updated linenr_T w_viewport_last_topfill; // topfill when the viewport was last updated
linenr_T w_viewport_last_skipcol; // skipcol when the viewport was last updated linenr_T w_viewport_last_skipcol; // skipcol when the viewport was last updated

View File

@ -1030,15 +1030,13 @@ void ui_ext_win_position(win_T *wp, bool validate)
void ui_ext_win_viewport(win_T *wp) void ui_ext_win_viewport(win_T *wp)
{ {
if ((wp == curwin || ui_has(kUIMultigrid)) && wp->w_viewport_invalid) { if ((wp == curwin || ui_has(kUIMultigrid)) && wp->w_viewport_invalid) {
int botline = wp->w_botline; const linenr_T line_count = wp->w_buffer->b_ml.ml_line_count;
int line_count = wp->w_buffer->b_ml.ml_line_count; // Avoid ml_get errors when producing "scroll_delta".
if (botline == line_count + 1 && wp->w_empty_rows == 0) { const linenr_T cur_topline = MIN(wp->w_topline, line_count);
// TODO(bfredl): The might be more cases to consider, like how does this const linenr_T cur_botline = MIN(wp->w_botline, line_count);
// interact with incomplete final line? Diff filler lines?
botline = wp->w_buffer->b_ml.ml_line_count;
}
int64_t delta = 0; int64_t delta = 0;
linenr_T last_topline = wp->w_viewport_last_topline; linenr_T last_topline = wp->w_viewport_last_topline;
linenr_T last_botline = wp->w_viewport_last_botline;
int last_topfill = wp->w_viewport_last_topfill; int last_topfill = wp->w_viewport_last_topfill;
int64_t last_skipcol = wp->w_viewport_last_skipcol; int64_t last_skipcol = wp->w_viewport_last_skipcol;
if (last_topline > line_count) { if (last_topline > line_count) {
@ -1047,19 +1045,39 @@ void ui_ext_win_viewport(win_T *wp)
last_topfill = 0; last_topfill = 0;
last_skipcol = MAXCOL; last_skipcol = MAXCOL;
} }
if (wp->w_topline < last_topline last_botline = MIN(last_botline, line_count);
|| (wp->w_topline == last_topline && wp->w_skipcol < last_skipcol)) { if (cur_topline < last_topline
delta -= win_get_text_height(wp, wp->w_topline, last_topline, wp->w_skipcol, last_skipcol); || (cur_topline == last_topline && wp->w_skipcol < last_skipcol)) {
} else if ((wp->w_topline > last_topline && wp->w_topline <= line_count) if (last_topline > 0 && cur_botline < last_topline) {
|| (wp->w_topline == last_topline && wp->w_skipcol > last_skipcol)) { // Scrolling too many lines: only give an approximate "scroll_delta".
delta += win_get_text_height(wp, last_topline, wp->w_topline, last_skipcol, wp->w_skipcol); delta -= win_get_text_height(wp, cur_topline, cur_botline, wp->w_skipcol, 0);
delta -= last_topline - cur_botline;
} else {
delta -= win_get_text_height(wp, cur_topline, last_topline, wp->w_skipcol, last_skipcol);
}
} else if (cur_topline > last_topline
|| (cur_topline == last_topline && wp->w_skipcol > last_skipcol)) {
if (last_botline > 0 && cur_topline > last_botline) {
// Scrolling too many lines: only give an approximate "scroll_delta".
delta += win_get_text_height(wp, last_topline, last_botline, last_skipcol, 0);
delta += cur_topline - last_botline;
} else {
delta += win_get_text_height(wp, last_topline, cur_topline, last_skipcol, wp->w_skipcol);
}
} }
delta += last_topfill; delta += last_topfill;
delta -= wp->w_topfill; delta -= wp->w_topfill;
ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, botline, linenr_T ev_botline = wp->w_botline;
if (ev_botline == line_count + 1 && wp->w_empty_rows == 0) {
// TODO(bfredl): The might be more cases to consider, like how does this
// interact with incomplete final line? Diff filler lines?
ev_botline = line_count;
}
ui_call_win_viewport(wp->w_grid_alloc.handle, wp->handle, wp->w_topline - 1, ev_botline,
wp->w_cursor.lnum - 1, wp->w_cursor.col, line_count, delta); wp->w_cursor.lnum - 1, wp->w_cursor.col, line_count, delta);
wp->w_viewport_invalid = false; wp->w_viewport_invalid = false;
wp->w_viewport_last_topline = wp->w_topline; wp->w_viewport_last_topline = wp->w_topline;
wp->w_viewport_last_botline = wp->w_botline;
wp->w_viewport_last_topfill = wp->w_topfill; wp->w_viewport_last_topfill = wp->w_topfill;
wp->w_viewport_last_skipcol = wp->w_skipcol; wp->w_viewport_last_skipcol = wp->w_skipcol;
} }

View File

@ -3631,6 +3631,221 @@ describe('ext_multigrid', function()
}} }}
end) end)
it('scroll_delta is approximated reasonably when scrolling many lines #24234', function()
command('setlocal number nowrap')
command('edit test/functional/fixtures/bigfile.txt')
screen:expect{grid=[[
## grid 1
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
{19: 1 }^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
{19: 2 }0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;|
{19: 3 }0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
{19: 4 }0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
{19: 5 }0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSIO|
{19: 6 }0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;; |
{19: 7 }0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; |
{19: 8 }0007;<control>;Cc;0;BN;;;;;N;BELL;;;; |
{19: 9 }0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;; |
{19: 10 }0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATIO|
{19: 11 }000A;<control>;Cc;0;B;;;;;N;LINE FEED (LF);;;; |
{19: 12 }000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;|
## grid 3
|
]], win_viewport={
[2] = {win = {id = 1000}, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
feed('G')
screen:expect{grid=[[
## grid 1
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
{19:30581 }E01E8;VARIATION SELECTOR-249;Mn;0;NSM;;;;;N;;;;|
{19:30582 }E01E9;VARIATION SELECTOR-250;Mn;0;NSM;;;;;N;;;;|
{19:30583 }E01EA;VARIATION SELECTOR-251;Mn;0;NSM;;;;;N;;;;|
{19:30584 }E01EB;VARIATION SELECTOR-252;Mn;0;NSM;;;;;N;;;;|
{19:30585 }E01EC;VARIATION SELECTOR-253;Mn;0;NSM;;;;;N;;;;|
{19:30586 }E01ED;VARIATION SELECTOR-254;Mn;0;NSM;;;;;N;;;;|
{19:30587 }E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;|
{19:30588 }E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;|
{19:30589 }F0000;<Plane 15 Private Use, First>;Co;0;L;;;;;|
{19:30590 }FFFFD;<Plane 15 Private Use, Last>;Co;0;L;;;;;N|
{19:30591 }100000;<Plane 16 Private Use, First>;Co;0;L;;;;|
{19:30592 }^10FFFD;<Plane 16 Private Use, Last>;Co;0;L;;;;;|
## grid 3
|
]], win_viewport={
[2] = {win = {id = 1000}, topline = 30580, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30580};
}}
feed('gg')
screen:expect{grid=[[
## grid 1
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
{19: 1 }^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
{19: 2 }0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;|
{19: 3 }0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
{19: 4 }0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
{19: 5 }0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSIO|
{19: 6 }0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;; |
{19: 7 }0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; |
{19: 8 }0007;<control>;Cc;0;BN;;;;;N;BELL;;;; |
{19: 9 }0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;; |
{19: 10 }0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULATIO|
{19: 11 }000A;<control>;Cc;0;B;;;;;N;LINE FEED (LF);;;; |
{19: 12 }000B;<control>;Cc;0;S;;;;;N;LINE TABULATION;;;;|
## grid 3
|
]], win_viewport={
[2] = {win = {id = 1000}, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
command('setlocal wrap')
screen:expect{grid=[[
## grid 1
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
{19: 1 }^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
{19: 2 }0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;|
{19: };; |
{19: 3 }0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
{19: 4 }0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
{19: 5 }0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSIO|
{19: }N;;;; |
{19: 6 }0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;; |
{19: 7 }0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; |
{19: 8 }0007;<control>;Cc;0;BN;;;;;N;BELL;;;; |
{19: 9 }0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;; |
{19: 10 }0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULA{1:@@@}|
## grid 3
|
]], win_viewport={
[2] = {win = {id = 1000}, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
feed('G')
screen:expect{grid=[[
## grid 1
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
{19:30587 }E01EE;VARIATION SELECTOR-255;Mn;0;NSM;;;;;N;;;;|
{19: }; |
{19:30588 }E01EF;VARIATION SELECTOR-256;Mn;0;NSM;;;;;N;;;;|
{19: }; |
{19:30589 }F0000;<Plane 15 Private Use, First>;Co;0;L;;;;;|
{19: }N;;;;; |
{19:30590 }FFFFD;<Plane 15 Private Use, Last>;Co;0;L;;;;;N|
{19: };;;;; |
{19:30591 }100000;<Plane 16 Private Use, First>;Co;0;L;;;;|
{19: };N;;;;; |
{19:30592 }^10FFFD;<Plane 16 Private Use, Last>;Co;0;L;;;;;|
{19: }N;;;;; |
## grid 3
|
]], win_viewport={
[2] = {win = {id = 1000}, topline = 30586, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30588};
}}
command('autocmd CursorMoved * ++once call line("w$")') -- FIXME: this should not be needed
feed('gg')
screen:expect{grid=[[
## grid 1
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
[2:-----------------------------------------------------]|
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
{19: 1 }^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
{19: 2 }0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;|
{19: };; |
{19: 3 }0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
{19: 4 }0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
{19: 5 }0004;<control>;Cc;0;BN;;;;;N;END OF TRANSMISSIO|
{19: }N;;;; |
{19: 6 }0005;<control>;Cc;0;BN;;;;;N;ENQUIRY;;;; |
{19: 7 }0006;<control>;Cc;0;BN;;;;;N;ACKNOWLEDGE;;;; |
{19: 8 }0007;<control>;Cc;0;BN;;;;;N;BELL;;;; |
{19: 9 }0008;<control>;Cc;0;BN;;;;;N;BACKSPACE;;;; |
{19: 10 }0009;<control>;Cc;0;S;;;;;N;CHARACTER TABULA{1:@@@}|
## grid 3
|
]], win_viewport={
[2] = {win = {id = 1000}, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
end)
it('does not crash when dragging mouse across grid boundary', function() it('does not crash when dragging mouse across grid boundary', function()
screen:try_resize(48, 8) screen:try_resize(48, 8)
screen:expect{grid=[[ screen:expect{grid=[[