aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/mouse.c24
-rw-r--r--test/old/testdir/test_scroll_opt.vim61
2 files changed, 81 insertions, 4 deletions
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index ead8dc2195..b890727a98 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -1410,9 +1410,22 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
} else {
row -= win_get_fill(win, lnum);
}
- count = plines_win_nofill(win, lnum, true);
+ count = plines_win_nofill(win, lnum, false);
} else {
- count = plines_win(win, lnum, true);
+ count = plines_win(win, lnum, false);
+ }
+
+ if (win->w_skipcol > 0 && lnum == win->w_topline) {
+ // Adjust for 'smoothscroll' clipping the top screen lines.
+ // A similar formula is used in curs_columns().
+ int width1 = win->w_width - win_col_off(win);
+ int skip_lines = 0;
+ if (win->w_skipcol > width1) {
+ skip_lines = (win->w_skipcol - width1) / (width1 + win_col_off2(win)) + 1;
+ } else if (win->w_skipcol > 0) {
+ skip_lines = 1;
+ }
+ count -= skip_lines;
}
if (count > row) {
@@ -1436,8 +1449,11 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
col = off;
}
col += row * (win->w_width_inner - off);
- // add skip column (for long wrapping line)
- col += win->w_skipcol;
+
+ // Add skip column for the topline.
+ if (lnum == win->w_topline) {
+ col += win->w_skipcol;
+ }
}
if (!win->w_p_wrap) {
diff --git a/test/old/testdir/test_scroll_opt.vim b/test/old/testdir/test_scroll_opt.vim
index 8d1942e037..3707e211fc 100644
--- a/test/old/testdir/test_scroll_opt.vim
+++ b/test/old/testdir/test_scroll_opt.vim
@@ -2,6 +2,7 @@
source check.vim
source screendump.vim
+source mouse.vim
func Test_reset_scroll()
let scr = &l:scroll
@@ -469,5 +470,65 @@ func Test_smoothscroll_cursor_position()
bwipeout!
endfunc
+" Test that mouse picking is still accurate when we have smooth scrolled lines
+func Test_smoothscroll_mouse_pos()
+ CheckNotGui
+ CheckUnix
+
+ let save_mouse = &mouse
+ "let save_term = &term
+ "let save_ttymouse = &ttymouse
+ set mouse=a "term=xterm ttymouse=xterm2
+
+ call NewWindow(10, 20)
+ setl smoothscroll wrap
+ " First line will wrap to 3 physical lines. 2nd/3rd lines are short lines.
+ call setline(1, ["abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", "line 2", "line 3"])
+
+ func s:check_mouse_click(row, col, buf_row, buf_col)
+ call MouseLeftClick(a:row, a:col)
+
+ call assert_equal(a:col, wincol())
+ call assert_equal(a:row, winline())
+ call assert_equal(a:buf_row, line('.'))
+ call assert_equal(a:buf_col, col('.'))
+ endfunc
+
+ " Check that clicking without scroll works first.
+ call s:check_mouse_click(3, 5, 1, 45)
+ call s:check_mouse_click(4, 1, 2, 1)
+ call s:check_mouse_click(4, 6, 2, 6)
+ call s:check_mouse_click(5, 1, 3, 1)
+ call s:check_mouse_click(5, 6, 3, 6)
+
+ " Smooth scroll, and checks that this didn't mess up mouse clicking
+ exe "normal \<C-E>"
+ call s:check_mouse_click(2, 5, 1, 45)
+ call s:check_mouse_click(3, 1, 2, 1)
+ call s:check_mouse_click(3, 6, 2, 6)
+ call s:check_mouse_click(4, 1, 3, 1)
+ call s:check_mouse_click(4, 6, 3, 6)
+
+ exe "normal \<C-E>"
+ call s:check_mouse_click(1, 5, 1, 45)
+ call s:check_mouse_click(2, 1, 2, 1)
+ call s:check_mouse_click(2, 6, 2, 6)
+ call s:check_mouse_click(3, 1, 3, 1)
+ call s:check_mouse_click(3, 6, 3, 6)
+
+ " Make a new first line 11 physical lines tall so it's taller than window
+ " height, to test overflow calculations with really long lines wrapping.
+ normal gg
+ call setline(1, "12345678901234567890"->repeat(11))
+ exe "normal 6\<C-E>"
+ call s:check_mouse_click(5, 1, 1, 201)
+ call s:check_mouse_click(6, 1, 2, 1)
+ call s:check_mouse_click(7, 1, 3, 1)
+
+ let &mouse = save_mouse
+ "let &term = save_term
+ "let &ttymouse = save_ttymouse
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab