diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/auevents.lua | 2 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 9 | ||||
-rw-r--r-- | src/nvim/edit.c | 6 | ||||
-rw-r--r-- | src/nvim/move.c | 14 | ||||
-rw-r--r-- | src/nvim/normal.c | 23 | ||||
-rw-r--r-- | src/nvim/window.c | 24 |
6 files changed, 72 insertions, 6 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..540542f409 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1230,6 +1230,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 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..218dcd289d 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1023,7 +1023,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 */ @@ -1098,17 +1098,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 @@ -1151,6 +1155,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 11e8d354e4..b09b99cf35 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. @@ -4146,7 +4160,8 @@ void scroll_redraw(int up, long count) } 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..47b6b7e713 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4976,6 +4976,30 @@ void shell_new_columns(void) } /* + * 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". */ void win_size_save(garray_T *gap) |