Merge pull request #14937 from dstein64/vim-8.1.2304

vim-patch:8.1.2304,8.1.2309,8.1.2319,8.1.2321
This commit is contained in:
Jan Edmund Lazo 2021-09-29 20:59:53 -04:00 committed by GitHub
commit 270cc1d70f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 210 additions and 1 deletions

View File

@ -2431,6 +2431,7 @@ getloclist({nr}) List list of location list items
getloclist({nr}, {what}) Dict get specific location list properties getloclist({nr}, {what}) Dict get specific location list properties
getmarklist([{buf}]) List list of global/local marks getmarklist([{buf}]) List list of global/local marks
getmatches([{win}]) List list of current matches getmatches([{win}]) List list of current matches
getmousepos() Dict last known mouse position
getpid() Number process ID of Vim getpid() Number process ID of Vim
getpos({expr}) List position of cursor, mark, etc. getpos({expr}) List position of cursor, mark, etc.
getqflist() List list of quickfix items getqflist() List list of quickfix items
@ -4709,7 +4710,8 @@ getchar([expr]) *getchar()*
When the user clicks a mouse button, the mouse event will be When the user clicks a mouse button, the mouse event will be
returned. The position can then be found in |v:mouse_col|, returned. The position can then be found in |v:mouse_col|,
|v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|. |v:mouse_lnum|, |v:mouse_winid| and |v:mouse_win|.
Mouse move events will be ignored. |getmousepos()| can also be used. Mouse move events will be
ignored.
This example positions the mouse as it would normally happen: > This example positions the mouse as it would normally happen: >
let c = getchar() let c = getchar()
if c == "\<LeftMouse>" && v:mouse_win > 0 if c == "\<LeftMouse>" && v:mouse_win > 0
@ -5099,6 +5101,35 @@ getmatches([{win}]) *getmatches()*
'pattern': 'FIXME', 'priority': 10, 'id': 2}] > 'pattern': 'FIXME', 'priority': 10, 'id': 2}] >
:unlet m :unlet m
< <
getmousepos() *getmousepos()*
Returns a Dictionary with the last known position of the
mouse. This can be used in a mapping for a mouse click. The
items are:
screenrow screen row
screencol screen column
winid Window ID of the click
winrow row inside "winid"
wincol column inside "winid"
line text line inside "winid"
column text column inside "winid"
All numbers are 1-based.
If not over a window, e.g. when in the command line, then only
"screenrow" and "screencol" are valid, the others are zero.
When on the status line below a window or the vertical
separater right of a window, the "line" and "column" values
are zero.
When the position is after the text then "column" is the
length of the text in bytes plus one.
If the mouse is over a focusable floating window then that
window is used.
When using |getchar()| the Vim variables |v:mouse_lnum|,
|v:mouse_col| and |v:mouse_winid| also provide these values.
*getpid()* *getpid()*
getpid() Return a Number which is the process ID of the Vim process. getpid() Return a Number which is the process ID of the Vim process.
This is a unique number, until Vim exits. This is a unique number, until Vim exits.

View File

@ -162,6 +162,7 @@ return {
getloclist={args={1, 2}}, getloclist={args={1, 2}},
getmarklist={args={0, 1}}, getmarklist={args={0, 1}},
getmatches={args={0, 1}}, getmatches={args={0, 1}},
getmousepos={},
getpid={}, getpid={},
getpos={args=1}, getpos={args=1},
getqflist={args={0, 1}}, getqflist={args={0, 1}},

View File

@ -3750,6 +3750,59 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr)
} }
} }
// "getmousepos()" function
void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
dict_T *d;
win_T *wp;
int row = mouse_row;
int col = mouse_col;
int grid = mouse_grid;
varnumber_T winid = 0;
varnumber_T winrow = 0;
varnumber_T wincol = 0;
linenr_T line = 0;
varnumber_T column = 0;
tv_dict_alloc_ret(rettv);
d = rettv->vval.v_dict;
tv_dict_add_nr(d, S_LEN("screenrow"), (varnumber_T)mouse_row + 1);
tv_dict_add_nr(d, S_LEN("screencol"), (varnumber_T)mouse_col + 1);
wp = mouse_find_win(&grid, &row, &col);
if (wp != NULL) {
int height = wp->w_height + wp->w_status_height;
// The height is adjusted by 1 when there is a bottom border. This is not
// necessary for a top border since `row` starts at -1 in that case.
if (row < height + wp->w_border_adj[2]) {
winid = wp->handle;
winrow = row + 1 + wp->w_border_adj[0]; // Adjust by 1 for top border
wincol = col + 1 + wp->w_border_adj[3]; // Adjust by 1 for left border
if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) {
char_u *p;
int count;
mouse_comp_pos(wp, &row, &col, &line);
// limit to text length plus one
p = ml_get_buf(wp->w_buffer, line, false);
count = (int)STRLEN(p);
if (col > count) {
col = count;
}
column = col + 1;
}
}
}
tv_dict_add_nr(d, S_LEN("winid"), winid);
tv_dict_add_nr(d, S_LEN("winrow"), winrow);
tv_dict_add_nr(d, S_LEN("wincol"), wincol);
tv_dict_add_nr(d, S_LEN("line"), (varnumber_T)line);
tv_dict_add_nr(d, S_LEN("column"), column);
}
/* /*
* "getpid()" function * "getpid()" function
*/ */

View File

@ -1384,4 +1384,128 @@ describe('ui/mouse/input', function()
end) -- level 3 - wrapped end) -- level 3 - wrapped
end) end)
it('getmousepos works correctly', function()
local winwidth = meths.get_option('winwidth')
-- Set winwidth=1 so that window sizes don't change.
meths.set_option('winwidth', 1)
command('tabedit')
local tabpage = meths.get_current_tabpage()
insert('hello')
command('vsplit')
local opts = {
relative='editor',
width=12,
height=1,
col=8,
row=1,
anchor='NW',
style='minimal',
border='single',
focusable=1
}
local float = meths.open_win(meths.get_current_buf(), false, opts)
command('redraw')
local lines = meths.get_option('lines')
local columns = meths.get_option('columns')
-- Test that screenrow and screencol are set properly for all positions.
for row = 0, lines - 1 do
for col = 0, columns - 1 do
-- Skip the X button that would close the tab.
if row ~= 0 or col ~= columns - 1 then
meths.input_mouse('left', 'press', '', 0, row, col)
meths.set_current_tabpage(tabpage)
local mousepos = funcs.getmousepos()
eq(row + 1, mousepos.screenrow)
eq(col + 1, mousepos.screencol)
-- All other values should be 0 when clicking on the command line.
if row == lines - 1 then
eq(0, mousepos.winid)
eq(0, mousepos.winrow)
eq(0, mousepos.wincol)
eq(0, mousepos.line)
eq(0, mousepos.column)
end
end
end
end
-- Test that mouse position values are properly set for the floating window
-- with a border. 1 is added to the height and width to account for the
-- border.
for win_row = 0, opts.height + 1 do
for win_col = 0, opts.width + 1 do
local row = win_row + opts.row
local col = win_col + opts.col
meths.input_mouse('left', 'press', '', 0, row, col)
local mousepos = funcs.getmousepos()
eq(float.id, mousepos.winid)
eq(win_row + 1, mousepos.winrow)
eq(win_col + 1, mousepos.wincol)
local line = 0
local column = 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)
end
eq(line, mousepos.line)
eq(column, mousepos.column)
end
end
-- Test that mouse position values are properly set for the floating
-- window, after removing the border.
opts.border = 'none'
meths.win_set_config(float, opts)
command('redraw')
for win_row = 0, opts.height - 1 do
for win_col = 0, opts.width - 1 do
local row = win_row + opts.row
local col = win_col + opts.col
meths.input_mouse('left', 'press', '', 0, row, col)
local mousepos = funcs.getmousepos()
eq(float.id, mousepos.winid)
eq(win_row + 1, mousepos.winrow)
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)
eq(line, mousepos.line)
eq(column, mousepos.column)
end
end
-- Test that mouse position values are properly set for ordinary windows.
-- Set the float to be unfocusable instead of closing, to additionally test
-- that getmousepos does not consider unfocusable floats. (see discussion
-- in PR #14937 for details).
opts.focusable = false
meths.win_set_config(float, opts)
command('redraw')
for nr = 1, 2 do
for win_row = 0, funcs.winheight(nr) - 1 do
for win_col = 0, funcs.winwidth(nr) - 1 do
local row = win_row + funcs.win_screenpos(nr)[1] - 1
local col = win_col + funcs.win_screenpos(nr)[2] - 1
meths.input_mouse('left', 'press', '', 0, row, col)
local mousepos = funcs.getmousepos()
eq(funcs.win_getid(nr), mousepos.winid)
eq(win_row + 1, mousepos.winrow)
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)
eq(line, mousepos.line)
eq(column, mousepos.column)
end
end
end
-- Restore state and release mouse.
command('tabclose!')
meths.set_option('winwidth', winwidth)
meths.input_mouse('left', 'release', '', 0, 0, 0)
end)
end) end)