From b83d8223ffee099634a4352443cb56a94ebfcc22 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Mon, 19 Oct 2020 12:27:17 -0400 Subject: implement scroll autocommand --- src/nvim/auevents.lua | 2 ++ src/nvim/buffer_defs.h | 3 +++ src/nvim/edit.c | 25 +++++++++++++++++++++++++ src/nvim/normal.c | 18 ++++++++++++++++++ 4 files changed, 48 insertions(+) (limited to 'src') diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 4391d997a7..2d733b0cb7 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -72,6 +72,7 @@ return { 'QuickFixCmdPre', -- before :make, :grep etc. 'QuitPre', -- before :quit 'RemoteReply', -- upon string reception from a remote vim + 'Scroll', -- after scrolling 'SessionLoadPost', -- after loading a session file 'ShellCmdPost', -- after ":!cmd" 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd". @@ -123,6 +124,7 @@ return { -- syntax file nvim_specific = { DirChanged=true, + Scroll=true, Signal=true, TabClosed=true, TabNew=true, diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 1223f2bdab..546054bb19 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1204,6 +1204,9 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window + linenr_T w_last_topline; ///< last known value for topline + colnr_T w_last_leftcol; ///< last known value for leftcol + // // Layout of the window in the screen. // May need to add "msg_scrolled" to "w_winrow" in rare situations. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index de2346a9d8..447f922767 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1482,6 +1482,31 @@ static void ins_redraw( } } + if (ready && has_event(EVENT_SCROLL) + && (curwin->w_last_topline != curwin->w_topline || + curwin->w_last_leftcol != curwin->w_leftcol)) { + + // XXX is the buf changedtick thing necessary? + // XXX apply_autocmds vs ins_apply_autocmds? + // XXX why can't we re-use normal_check_window_scrolled()? + + aco_save_T aco; + varnumber_T tick = buf_get_changedtick(curbuf); + + // save and restore curwin and curbuf, in case the autocmd changes them + aucmd_prepbuf(&aco, curbuf); + apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + aucmd_restbuf(&aco); + curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); + if (tick != buf_get_changedtick(curbuf)) { // see ins_apply_autocmds() + u_save(curwin->w_cursor.lnum, + (linenr_T)(curwin->w_cursor.lnum + 1)); + } + + curwin->w_last_topline = curwin->w_topline; + curwin->w_last_leftcol = curwin->w_leftcol; + } + if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin) && conceal_cursor_moved) { redrawWinline(curwin, curwin->w_cursor.lnum); diff --git a/src/nvim/normal.c b/src/nvim/normal.c index a51aa0dc07..eb15204c63 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1193,6 +1193,22 @@ static void normal_check_interrupt(NormalState *s) } } +static void normal_check_window_scrolled(NormalState *s) +{ + // XXX why is has_event necessary? + + // Trigger Scroll if the window moved. + if (!finish_op && has_event(EVENT_SCROLL) + && (curwin->w_last_topline != curwin->w_topline || + curwin->w_last_leftcol != curwin->w_leftcol)) { + + apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + + curwin->w_last_topline = curwin->w_topline; + curwin->w_last_leftcol = curwin->w_leftcol; + } +} + static void normal_check_cursor_moved(NormalState *s) { // Trigger CursorMoved if the cursor moved. @@ -1279,6 +1295,7 @@ static void normal_redraw(NormalState *s) xfree(p); } + // show fileinfo after redraw if (need_fileinfo && !shortmess(SHM_FILEINFO)) { fileinfo(false, true, false); @@ -1318,6 +1335,7 @@ static int normal_check(VimState *state) } else if (do_redraw || stuff_empty()) { normal_check_cursor_moved(s); normal_check_text_changed(s); + normal_check_window_scrolled(s); // Updating diffs from changed() does not always work properly, // esp. updating folds. Do an update just before redrawing if -- cgit From d4033db6a0a3b9e1f33ca3760377c8a637e80c85 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 24 Oct 2020 04:56:43 -0400 Subject: scroll: cleanup unnecessary code & comments --- src/nvim/edit.c | 15 --------------- src/nvim/normal.c | 2 -- 2 files changed, 17 deletions(-) (limited to 'src') diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 447f922767..949f5d5a62 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1486,22 +1486,7 @@ static void ins_redraw( && (curwin->w_last_topline != curwin->w_topline || curwin->w_last_leftcol != curwin->w_leftcol)) { - // XXX is the buf changedtick thing necessary? - // XXX apply_autocmds vs ins_apply_autocmds? - // XXX why can't we re-use normal_check_window_scrolled()? - - aco_save_T aco; - varnumber_T tick = buf_get_changedtick(curbuf); - - // save and restore curwin and curbuf, in case the autocmd changes them - aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); - aucmd_restbuf(&aco); - curbuf->b_last_changedtick_pum = buf_get_changedtick(curbuf); - if (tick != buf_get_changedtick(curbuf)) { // see ins_apply_autocmds() - u_save(curwin->w_cursor.lnum, - (linenr_T)(curwin->w_cursor.lnum + 1)); - } curwin->w_last_topline = curwin->w_topline; curwin->w_last_leftcol = curwin->w_leftcol; diff --git a/src/nvim/normal.c b/src/nvim/normal.c index eb15204c63..80ed9bd2b6 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1195,8 +1195,6 @@ static void normal_check_interrupt(NormalState *s) static void normal_check_window_scrolled(NormalState *s) { - // XXX why is has_event necessary? - // Trigger Scroll if the window moved. if (!finish_op && has_event(EVENT_SCROLL) && (curwin->w_last_topline != curwin->w_topline || -- cgit From a1596f0b0bb7e2a84e062a27fabe618d085a2947 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 24 Oct 2020 20:16:58 -0400 Subject: scroll: use win->w_viewport_invalid --- src/nvim/buffer_defs.h | 3 --- src/nvim/edit.c | 7 +------ src/nvim/normal.c | 8 +------- 3 files changed, 2 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 546054bb19..1223f2bdab 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1204,9 +1204,6 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window - linenr_T w_last_topline; ///< last known value for topline - colnr_T w_last_leftcol; ///< last known value for leftcol - // // Layout of the window in the screen. // May need to add "msg_scrolled" to "w_winrow" in rare situations. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 949f5d5a62..56202177c0 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1483,13 +1483,8 @@ static void ins_redraw( } if (ready && has_event(EVENT_SCROLL) - && (curwin->w_last_topline != curwin->w_topline || - curwin->w_last_leftcol != curwin->w_leftcol)) { - + && curwin->w_viewport_invalid) { apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); - - curwin->w_last_topline = curwin->w_topline; - curwin->w_last_leftcol = curwin->w_leftcol; } if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin) diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 80ed9bd2b6..2e49108028 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1197,13 +1197,8 @@ static void normal_check_window_scrolled(NormalState *s) { // Trigger Scroll if the window moved. if (!finish_op && has_event(EVENT_SCROLL) - && (curwin->w_last_topline != curwin->w_topline || - curwin->w_last_leftcol != curwin->w_leftcol)) { - + && curwin->w_viewport_invalid) { apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); - - curwin->w_last_topline = curwin->w_topline; - curwin->w_last_leftcol = curwin->w_leftcol; } } @@ -1293,7 +1288,6 @@ static void normal_redraw(NormalState *s) xfree(p); } - // show fileinfo after redraw if (need_fileinfo && !shortmess(SHM_FILEINFO)) { fileinfo(false, true, false); -- cgit From d2a38dab8085ddb973393ca7f077ff65d64f60ef Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sun, 25 Oct 2020 02:25:22 -0400 Subject: move.c: dont invalidate viewport when no scroll happened --- src/nvim/move.c | 14 ++++++++++++-- src/nvim/normal.c | 10 ++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/move.c b/src/nvim/move.c index e2a304efa5..8084461d3a 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1020,7 +1020,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, /* * Scroll the current window down by "line_count" logical lines. "CTRL-Y" */ -void +bool scrolldown ( long line_count, int byfold /* true: count a closed fold as one line */ @@ -1095,17 +1095,21 @@ scrolldown ( foldAdjustCursor(); coladvance(curwin->w_curswant); } + return moved; } /* * Scroll the current window up by "line_count" logical lines. "CTRL-E" */ -void +bool scrollup ( long line_count, int byfold /* true: count a closed fold as one line */ ) { + linenr_T topline = curwin->w_topline; + linenr_T botline = curwin->w_botline; + if ((byfold && hasAnyFolding(curwin)) || curwin->w_p_diff) { // count each sequence of folded lines as one logical line @@ -1148,6 +1152,12 @@ scrollup ( ~(VALID_WROW|VALID_WCOL|VALID_CHEIGHT|VALID_CROW|VALID_VIRTCOL); coladvance(curwin->w_curswant); } + + bool moved = + topline != curwin->w_topline || + botline != curwin->w_botline; + + return moved; } /* diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2e49108028..f6add44f6a 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4117,10 +4117,10 @@ void scroll_redraw(int up, long count) int prev_topfill = curwin->w_topfill; linenr_T prev_lnum = curwin->w_cursor.lnum; - if (up) - scrollup(count, true); - else + bool moved = up ? + scrollup(count, true) : scrolldown(count, true); + if (get_scrolloff_value()) { // Adjust the cursor position for 'scrolloff'. Mark w_topline as // valid, otherwise the screen jumps back at the end of the file. @@ -4152,7 +4152,9 @@ void scroll_redraw(int up, long count) } if (curwin->w_cursor.lnum != prev_lnum) coladvance(curwin->w_curswant); - curwin->w_viewport_invalid = true; + // XXX: can `moved` be used to prevent other work here? + if (moved) + curwin->w_viewport_invalid = true; redraw_later(VALID); } -- cgit From bc21843228ce255bee8108a78c3c509743c8fe0c Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Wed, 28 Oct 2020 03:59:26 -0400 Subject: feat: implement a working WinScrolled autocmd --- src/nvim/auevents.lua | 4 ++-- src/nvim/buffer_defs.h | 9 +++++++++ src/nvim/edit.c | 7 ++++--- src/nvim/normal.c | 12 ++++++++---- src/nvim/window.c | 24 ++++++++++++++++++++++++ 5 files changed, 47 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 2d733b0cb7..ea2db41668 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -72,7 +72,6 @@ return { 'QuickFixCmdPre', -- before :make, :grep etc. 'QuitPre', -- before :quit 'RemoteReply', -- upon string reception from a remote vim - 'Scroll', -- after scrolling 'SessionLoadPost', -- after loading a session file 'ShellCmdPost', -- after ":!cmd" 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd". @@ -113,6 +112,7 @@ return { 'WinEnter', -- after entering a window 'WinLeave', -- before leaving a window 'WinNew', -- when entering a new window + 'WinScrolled', -- after scrolling a window }, aliases = { BufCreate = 'BufAdd', @@ -124,7 +124,6 @@ return { -- syntax file nvim_specific = { DirChanged=true, - Scroll=true, Signal=true, TabClosed=true, TabNew=true, @@ -134,5 +133,6 @@ return { UIEnter=true, UILeave=true, WinClosed=true, + WinScrolled=true, }, } diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 1223f2bdab..ba71ac6b2b 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1204,6 +1204,15 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window + /* + * "w_last_topline" and "w_last_leftcol" are used to determine if + * a Scroll autocommand should be emitted. + */ + linenr_T w_last_topline; ///< last known value for topline + colnr_T w_last_leftcol; ///< last known value for leftcol + int w_last_width; ///< last known value for width + int w_last_height; ///< last known value for height + // // Layout of the window in the screen. // May need to add "msg_scrolled" to "w_winrow" in rare situations. diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 56202177c0..5ea6716c0a 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1482,9 +1482,10 @@ static void ins_redraw( } } - if (ready && has_event(EVENT_SCROLL) - && curwin->w_viewport_invalid) { - apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + // Trigger Scroll if viewport changed. + if (ready && has_event(EVENT_WINSCROLLED) + && win_did_scroll(curwin)) { + do_autocmd_winscrolled(curwin); } if (curwin->w_p_cole > 0 && conceal_cursor_line(curwin) diff --git a/src/nvim/normal.c b/src/nvim/normal.c index f6add44f6a..2812297347 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1195,10 +1195,10 @@ static void normal_check_interrupt(NormalState *s) static void normal_check_window_scrolled(NormalState *s) { - // Trigger Scroll if the window moved. - if (!finish_op && has_event(EVENT_SCROLL) - && curwin->w_viewport_invalid) { - apply_autocmds(EVENT_SCROLL, NULL, NULL, false, curbuf); + // Trigger Scroll if the viewport changed. + if (!finish_op && has_event(EVENT_WINSCROLLED) + && win_did_scroll(curwin)) { + do_autocmd_winscrolled(curwin); } } @@ -1325,6 +1325,10 @@ static int normal_check(VimState *state) if (skip_redraw || exmode_active) { skip_redraw = false; } else if (do_redraw || stuff_empty()) { + // Need to make sure w_topline and w_leftcol are correct before + // normal_check_window_scrolled() is called. + update_topline(); + normal_check_cursor_moved(s); normal_check_text_changed(s); normal_check_window_scrolled(s); diff --git a/src/nvim/window.c b/src/nvim/window.c index 4931221e7a..bbc039d151 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4965,6 +4965,30 @@ void shell_new_columns(void) win_reconfig_floats(); // The size of floats might change } +/* + * Check if "wp" has scrolled since last time it was checked + */ +bool win_did_scroll(win_T *wp) +{ + return (curwin->w_last_topline != curwin->w_topline || + curwin->w_last_leftcol != curwin->w_leftcol || + curwin->w_last_width != curwin->w_width || + curwin->w_last_height != curwin->w_height); +} + +/* + * Trigger WinScrolled autocmd + */ +void do_autocmd_winscrolled(win_T *wp) +{ + apply_autocmds(EVENT_WINSCROLLED, NULL, NULL, false, curbuf); + + wp->w_last_topline = wp->w_topline; + wp->w_last_leftcol = wp->w_leftcol; + wp->w_last_width = wp->w_width; + wp->w_last_height = wp->w_height; +} + /* * Save the size of all windows in "gap". */ -- cgit From c7c865214655f7d88fde85ed4947f07319c14182 Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sun, 1 Nov 2020 05:00:20 -0500 Subject: fix: remove xxx comment --- src/nvim/normal.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 2812297347..f291adaffe 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4156,7 +4156,6 @@ void scroll_redraw(int up, long count) } if (curwin->w_cursor.lnum != prev_lnum) coladvance(curwin->w_curswant); - // XXX: can `moved` be used to prevent other work here? if (moved) curwin->w_viewport_invalid = true; redraw_later(VALID); -- cgit From 4ed6f6949737749521b342d164d8695e8958d02f Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Fri, 6 Nov 2020 20:06:40 -0500 Subject: my fight with the linter --- src/nvim/buffer_defs.h | 6 ++---- src/nvim/move.c | 31 +++++++++++-------------------- src/nvim/normal.c | 6 ++++-- src/nvim/window.c | 17 +++++++---------- 4 files changed, 24 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 540542f409..b72ca51517 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1230,10 +1230,8 @@ struct window_S { colnr_T w_skipcol; // starting column when a single line // doesn't fit in the window - /* - * "w_last_topline" and "w_last_leftcol" are used to determine if - * a Scroll autocommand should be emitted. - */ + // "w_last_topline" and "w_last_leftcol" are used to determine if + // a Scroll autocommand should be emitted. linenr_T w_last_topline; ///< last known value for topline colnr_T w_last_leftcol; ///< last known value for leftcol int w_last_width; ///< last known value for width diff --git a/src/nvim/move.c b/src/nvim/move.c index 218dcd289d..549a135a5e 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1020,16 +1020,12 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, *ecolp = ecol + coloff; } -/* - * Scroll the current window down by "line_count" logical lines. "CTRL-Y" - */ -bool -scrolldown ( - long line_count, - int byfold /* true: count a closed fold as one line */ -) +/// Scroll the current window down by "line_count" logical lines. "CTRL-Y" +/// @param line_count number of lines to scroll +/// @param byfold if true, count a closed fold as one line +bool scrolldown(long line_count, int byfold) { - int done = 0; /* total # of physical lines done */ + int done = 0; // total # of physical lines done /* Make sure w_topline is at the first of a sequence of folded lines. */ (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL); @@ -1101,14 +1097,10 @@ scrolldown ( return moved; } -/* - * Scroll the current window up by "line_count" logical lines. "CTRL-E" - */ -bool -scrollup ( - long line_count, - int byfold /* true: count a closed fold as one line */ -) +/// Scroll the current window up by "line_count" logical lines. "CTRL-E" +/// @param line_count number of lines to scroll +/// @param byfold if true, count a closed fold as one line +bool scrollup(long line_count, int byfold) { linenr_T topline = curwin->w_topline; linenr_T botline = curwin->w_botline; @@ -1156,9 +1148,8 @@ scrollup ( coladvance(curwin->w_curswant); } - bool moved = - topline != curwin->w_topline || - botline != curwin->w_botline; + bool moved = topline != curwin->w_topline + || botline != curwin->w_botline; return moved; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index b09b99cf35..771ca732f4 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -4158,10 +4158,12 @@ void scroll_redraw(int up, long count) curwin->w_valid |= VALID_TOPLINE; } } - if (curwin->w_cursor.lnum != prev_lnum) + if (curwin->w_cursor.lnum != prev_lnum) { coladvance(curwin->w_curswant); - if (moved) + } + if (moved) { curwin->w_viewport_invalid = true; + } redraw_later(curwin, VALID); } diff --git a/src/nvim/window.c b/src/nvim/window.c index 47b6b7e713..9d918ebeb0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4975,20 +4975,17 @@ void shell_new_columns(void) win_reconfig_floats(); // The size of floats might change } -/* - * Check if "wp" has scrolled since last time it was checked - */ +/// Check if "wp" has scrolled since last time it was checked +/// @param wp the window to check bool win_did_scroll(win_T *wp) { - return (curwin->w_last_topline != curwin->w_topline || - curwin->w_last_leftcol != curwin->w_leftcol || - curwin->w_last_width != curwin->w_width || - curwin->w_last_height != curwin->w_height); + return (curwin->w_last_topline != curwin->w_topline + || curwin->w_last_leftcol != curwin->w_leftcol + || curwin->w_last_width != curwin->w_width + || curwin->w_last_height != curwin->w_height); } -/* - * Trigger WinScrolled autocmd - */ +/// Trigger WinScrolled autocmd void do_autocmd_winscrolled(win_T *wp) { apply_autocmds(EVENT_WINSCROLLED, NULL, NULL, false, curbuf); -- cgit From d7f639d4e8b46c168f66337bc12233818d39e8ec Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Sat, 7 Nov 2020 03:47:52 -0500 Subject: fix: lint doc-comments --- src/nvim/move.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/nvim/move.c b/src/nvim/move.c index 549a135a5e..ccd19a81de 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1021,6 +1021,7 @@ void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, } /// Scroll the current window down by "line_count" logical lines. "CTRL-Y" +/// /// @param line_count number of lines to scroll /// @param byfold if true, count a closed fold as one line bool scrolldown(long line_count, int byfold) @@ -1098,6 +1099,7 @@ bool scrolldown(long line_count, int byfold) } /// Scroll the current window up by "line_count" logical lines. "CTRL-E" +/// /// @param line_count number of lines to scroll /// @param byfold if true, count a closed fold as one line bool scrollup(long line_count, int byfold) -- cgit