From d974a3dcbb3757ebeb78fa64054c795ab7acdf1a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 15 Oct 2023 17:19:01 +0800 Subject: [PATCH] vim-patch:9.0.2032: cannot get mouse click pos for tab or virt text (#25653) Problem: Cannot accurately get mouse clicking position when clicking on a TAB or with virtual text. Solution: Add a "coladd" field to getmousepos() result. closes: vim/vim#13335 https://github.com/vim/vim/commit/f5a94d5165bb9e390797da50a1fa7a87df3fbee4 --- runtime/doc/builtin.txt | 2 ++ runtime/lua/vim/_meta/vimfn.lua | 2 ++ src/nvim/eval.lua | 2 ++ src/nvim/mouse.c | 15 ++++++++------ src/nvim/move.c | 2 +- test/functional/ui/fold_spec.lua | 7 ++++--- test/functional/ui/mouse_spec.lua | 8 ++++++++ test/old/testdir/test_functions.vim | 31 +++++++++++++++++++++++++++++ 8 files changed, 59 insertions(+), 10 deletions(-) diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index c09c0d552e..ceecc61b97 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -2674,6 +2674,8 @@ getmousepos() *getmousepos()* wincol column inside "winid" line text line inside "winid" column text column inside "winid" + coladd offset (in screen columns) from the + start of the clicked char All numbers are 1-based. If not over a window, e.g. when in the command line, then only diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index a2d9ce5bc4..2b79feec8e 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -3242,6 +3242,8 @@ function vim.fn.getmatches(win) end --- wincol column inside "winid" --- line text line inside "winid" --- column text column inside "winid" +--- coladd offset (in screen columns) from the +--- start of the clicked char --- All numbers are 1-based. --- --- If not over a window, e.g. when in the command line, then only diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 6ba5a171f9..46d17d8c03 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -4034,6 +4034,8 @@ M.funcs = { wincol column inside "winid" line text line inside "winid" column text column inside "winid" + coladd offset (in screen columns) from the + start of the clicked char All numbers are 1-based. If not over a window, e.g. when in the command line, then only diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 75c399bcad..a76e4b7e53 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -243,9 +243,7 @@ static int get_fpos_of_mouse(pos_T *mpos) return IN_UNKNOWN; } - mpos->col = vcol2col(wp, mpos->lnum, col); - - mpos->coladd = 0; + mpos->col = vcol2col(wp, mpos->lnum, col, &mpos->coladd); return IN_BUFFER; } @@ -1755,8 +1753,8 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp) /// Convert a virtual (screen) column to a character column. /// The first column is zero. -colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol) - FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +colnr_T vcol2col(win_T *wp, linenr_T lnum, colnr_T vcol, colnr_T *coladdp) + FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT { // try to advance to the specified column char *line = ml_get_buf(wp->w_buffer, lnum); @@ -1772,6 +1770,9 @@ colnr_T vcol2col(win_T *const wp, const linenr_T lnum, const colnr_T vcol) } clear_chartabsize_arg(&cts); + if (coladdp != NULL) { + *coladdp = vcol - cts.cts_vcol; + } return (colnr_T)(cts.cts_ptr - line); } @@ -1927,6 +1928,7 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) varnumber_T wincol = 0; linenr_T lnum = 0; varnumber_T column = 0; + colnr_T coladd = 0; tv_dict_alloc_ret(rettv); dict_T *d = rettv->vval.v_dict; @@ -1945,7 +1947,7 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) wincol = col + 1 + wp->w_wincol_off; // Adjust by 1 for left border if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) { (void)mouse_comp_pos(wp, &row, &col, &lnum); - col = vcol2col(wp, lnum, col); + col = vcol2col(wp, lnum, col, &coladd); column = col + 1; } } @@ -1955,4 +1957,5 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_dict_add_nr(d, S_LEN("wincol"), wincol); tv_dict_add_nr(d, S_LEN("line"), (varnumber_T)lnum); tv_dict_add_nr(d, S_LEN("column"), column); + tv_dict_add_nr(d, S_LEN("coladd"), coladd); } diff --git a/src/nvim/move.c b/src/nvim/move.c index dfd2bf795d..8be05aaa24 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -1142,7 +1142,7 @@ void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// returned. static int virtcol2col(win_T *wp, linenr_T lnum, int vcol) { - int offset = vcol2col(wp, lnum, vcol - 1); + int offset = vcol2col(wp, lnum, vcol - 1, NULL); char *line = ml_get_buf(wp->w_buffer, lnum); char *p = line + offset; diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index 264c0355ae..9a0182ea29 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -2155,13 +2155,14 @@ describe("folded lines", function() meths.input_mouse('left', 'press', '', multigrid and 2 or 0, 4, 0) eq({ - column = 1, - line = 3, screencol = 1, screenrow = 5, - wincol = 1, winid = 1000, + wincol = 1, winrow = 5, + line = 3, + column = 1, + coladd = 0, }, funcs.getmousepos()) meths.buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{"more virt_line below line 2", ""}}} }) diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index fd24174f74..1356ba3db8 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -1717,6 +1717,7 @@ describe('ui/mouse/input', function() eq(0, mousepos.wincol) eq(0, mousepos.line) eq(0, mousepos.column) + eq(0, mousepos.coladd) end end end @@ -1736,15 +1737,18 @@ describe('ui/mouse/input', function() eq(win_col + 1, mousepos.wincol) local line = 0 local column = 0 + local coladd = 0 if win_row > 0 and win_row < opts.height + 1 and win_col > 0 and win_col < opts.width + 1 then -- Because of border, win_row and win_col don't need to be -- incremented by 1. line = math.min(win_row, funcs.line('$')) column = math.min(win_col, #funcs.getline(line) + 1) + coladd = win_col - column end eq(line, mousepos.line) eq(column, mousepos.column) + eq(coladd, mousepos.coladd) end end @@ -1764,8 +1768,10 @@ describe('ui/mouse/input', function() eq(win_col + 1, mousepos.wincol) local line = math.min(win_row + 1, funcs.line('$')) local column = math.min(win_col + 1, #funcs.getline(line) + 1) + local coladd = win_col + 1 - column eq(line, mousepos.line) eq(column, mousepos.column) + eq(coladd, mousepos.coladd) end end @@ -1788,8 +1794,10 @@ describe('ui/mouse/input', function() eq(win_col + 1, mousepos.wincol) local line = math.min(win_row + 1, funcs.line('$')) local column = math.min(win_col + 1, #funcs.getline(line) + 1) + local coladd = win_col + 1 - column eq(line, mousepos.line) eq(column, mousepos.column) + eq(coladd, mousepos.coladd) end end end diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim index 6a4d80d94d..9448ff21aa 100644 --- a/test/old/testdir/test_functions.vim +++ b/test/old/testdir/test_functions.vim @@ -3068,6 +3068,7 @@ func Test_getmousepos() \ wincol: 1, \ line: 1, \ column: 1, + \ coladd: 0, \ }, getmousepos()) call Ntest_setmouse(1, 2) call assert_equal(#{ @@ -3078,6 +3079,7 @@ func Test_getmousepos() \ wincol: 2, \ line: 1, \ column: 1, + \ coladd: 1, \ }, getmousepos()) call Ntest_setmouse(1, 8) call assert_equal(#{ @@ -3088,6 +3090,7 @@ func Test_getmousepos() \ wincol: 8, \ line: 1, \ column: 1, + \ coladd: 7, \ }, getmousepos()) call Ntest_setmouse(1, 9) call assert_equal(#{ @@ -3098,6 +3101,7 @@ func Test_getmousepos() \ wincol: 9, \ line: 1, \ column: 2, + \ coladd: 0, \ }, getmousepos()) call Ntest_setmouse(1, 12) call assert_equal(#{ @@ -3108,6 +3112,7 @@ func Test_getmousepos() \ wincol: 12, \ line: 1, \ column: 2, + \ coladd: 3, \ }, getmousepos()) call Ntest_setmouse(1, 25) call assert_equal(#{ @@ -3118,6 +3123,29 @@ func Test_getmousepos() \ wincol: 25, \ line: 1, \ column: 4, + \ coladd: 0, + \ }, getmousepos()) + call Ntest_setmouse(1, 28) + call assert_equal(#{ + \ screenrow: 1, + \ screencol: 28, + \ winid: win_getid(), + \ winrow: 1, + \ wincol: 28, + \ line: 1, + \ column: 7, + \ coladd: 0, + \ }, getmousepos()) + call Ntest_setmouse(1, 29) + call assert_equal(#{ + \ screenrow: 1, + \ screencol: 29, + \ winid: win_getid(), + \ winrow: 1, + \ wincol: 29, + \ line: 1, + \ column: 8, + \ coladd: 0, \ }, getmousepos()) call Ntest_setmouse(1, 50) call assert_equal(#{ @@ -3128,6 +3156,7 @@ func Test_getmousepos() \ wincol: 50, \ line: 1, \ column: 8, + \ coladd: 21, \ }, getmousepos()) " If the mouse is positioned past the last buffer line, "line" and "column" @@ -3141,6 +3170,7 @@ func Test_getmousepos() \ wincol: 25, \ line: 1, \ column: 4, + \ coladd: 0, \ }, getmousepos()) call Ntest_setmouse(2, 50) call assert_equal(#{ @@ -3151,6 +3181,7 @@ func Test_getmousepos() \ wincol: 50, \ line: 1, \ column: 8, + \ coladd: 21, \ }, getmousepos()) bwipe! endfunc