diff options
Diffstat (limited to 'src/nvim')
-rw-r--r-- | src/nvim/auevents.lua | 2 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 7 | ||||
-rw-r--r-- | src/nvim/edit.c | 6 | ||||
-rw-r--r-- | src/nvim/move.c | 37 | ||||
-rw-r--r-- | src/nvim/normal.c | 27 | ||||
-rw-r--r-- | src/nvim/window.c | 21 |
6 files changed, 78 insertions, 22 deletions
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua index 10647c01a4..9c28398f5b 100644 --- a/src/nvim/auevents.lua +++ b/src/nvim/auevents.lua @@ -113,6 +113,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', @@ -133,5 +134,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 4efc341875..b72ca51517 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1230,6 +1230,13 @@ 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 3e62ed9036..d7cca9ba36 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1482,6 +1482,12 @@ static void ins_redraw( } } + // 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) && conceal_cursor_moved) { redrawWinline(curwin, curwin->w_cursor.lnum); diff --git a/src/nvim/move.c b/src/nvim/move.c index 98a7792a09..ccd19a81de 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1020,16 +1020,13 @@ 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" - */ -void -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); @@ -1098,17 +1095,18 @@ scrolldown ( foldAdjustCursor(); coladvance(curwin->w_curswant); } + return moved; } -/* - * Scroll the current window up by "line_count" logical lines. "CTRL-E" - */ -void -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; + if ((byfold && hasAnyFolding(curwin)) || curwin->w_p_diff) { // count each sequence of folded lines as one logical line @@ -1151,6 +1149,11 @@ 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 11e8d354e4..771ca732f4 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -1197,6 +1197,15 @@ static void normal_check_interrupt(NormalState *s) } } +static void normal_check_window_scrolled(NormalState *s) +{ + // Trigger Scroll if the viewport changed. + if (!finish_op && has_event(EVENT_WINSCROLLED) + && win_did_scroll(curwin)) { + do_autocmd_winscrolled(curwin); + } +} + static void normal_check_cursor_moved(NormalState *s) { // Trigger CursorMoved if the cursor moved. @@ -1320,8 +1329,13 @@ 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); // Updating diffs from changed() does not always work properly, // esp. updating folds. Do an update just before redrawing if @@ -4111,10 +4125,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. @@ -4144,9 +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); - curwin->w_viewport_invalid = true; + } + if (moved) { + curwin->w_viewport_invalid = true; + } redraw_later(curwin, VALID); } diff --git a/src/nvim/window.c b/src/nvim/window.c index 2147bd4fc7..9d918ebeb0 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4975,6 +4975,27 @@ 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 +/// @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); +} + +/// 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". */ |