mirror of
https://github.com/neovim/neovim.git
synced 2026-02-09 13:28:47 +00:00
feat(ui): show "empty" cursor behind unfocused floatwin #37624
Problem: There is no indication of when cursor is "behind" an unfocused, floating window. Solution: Set underline cursor to indicate when an unfocused floatwin is over the active cursor.
This commit is contained in:
@@ -571,6 +571,17 @@ void ui_flush(void)
|
||||
// by nvim core, not the compositor)
|
||||
win_ui_flush(false);
|
||||
}
|
||||
|
||||
// Show "empty box" (underline style) cursor if behind a floatwin.
|
||||
if (!(State & MODE_CMDLINE)) {
|
||||
bool cursor_obscured = ui_cursor_is_behind_floatwin();
|
||||
int new_idx = cursor_obscured ? SHAPE_IDX_R : cursor_get_mode_idx();
|
||||
if (ui_mode_idx != new_idx) {
|
||||
ui_mode_idx = new_idx;
|
||||
pending_mode_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (pending_mode_info_update) {
|
||||
Arena arena = ARENA_EMPTY;
|
||||
Array style = mode_style_array(&arena);
|
||||
@@ -674,6 +685,22 @@ void ui_cursor_shape(void)
|
||||
conceal_check_cursor_line();
|
||||
}
|
||||
|
||||
/// Check if the cursor is behind a floating window (only in compositor mode).
|
||||
/// @return true if cursor is obscured by a float with higher zindex
|
||||
static bool ui_cursor_is_behind_floatwin(void)
|
||||
{
|
||||
if (!ui_comp_should_draw()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int crow = curwin->w_winrow + curwin->w_winrow_off + curwin->w_wrow;
|
||||
int ccol = curwin->w_wincol + curwin->w_wincol_off
|
||||
+ (curwin->w_p_rl ? curwin->w_view_width - curwin->w_wcol - 1 : curwin->w_wcol);
|
||||
|
||||
ScreenGrid *top_grid = ui_comp_get_grid_at_coord(crow, ccol);
|
||||
return top_grid != &curwin->w_grid_alloc && top_grid != &default_grid;
|
||||
}
|
||||
|
||||
/// Returns true if the given UI extension is enabled.
|
||||
bool ui_has(UIExtension ext)
|
||||
{
|
||||
|
||||
@@ -11251,6 +11251,417 @@ describe('float window', function()
|
||||
eq('Vim(set):E474: Invalid argument: winborder=+,-,+,|,+,-,+,', pcall_err(command, [[set winborder=+,-,+,\|,+,-,+,]]))
|
||||
eq('Vim(set):E474: Invalid argument: winborder=custom', pcall_err(command, 'set winborder=custom'))
|
||||
end)
|
||||
|
||||
it('cursor shape when the cursor is covered by a floating window', function()
|
||||
local normal_win = api.nvim_get_current_win()
|
||||
api.nvim_buf_set_lines(0, 0, -1, true, { 'one', 'two' })
|
||||
api.nvim_win_set_cursor(0, { 2, 2 })
|
||||
local buf = api.nvim_create_buf(false, false)
|
||||
api.nvim_buf_set_lines(buf, 0, 0, true, { 'the only line' })
|
||||
local win = api.nvim_open_win(buf, false, { relative = 'editor', row = 0, col = 0, height = 2, width = 20 })
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
tw^o |
|
||||
{0:~ }|*4
|
||||
## grid 3
|
||||
|
|
||||
## grid 4
|
||||
{1:the only line }|
|
||||
{1: }|
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 6, startcol = 0, startrow = 0, width = 40, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[4] = { 1001, 'NW', 1, 0, 0, true, 50, 1, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1:the only line } |
|
||||
{1: ^ } |
|
||||
{0:~ }|*4
|
||||
|
|
||||
]],
|
||||
mode = 'replace',
|
||||
}
|
||||
end
|
||||
api.nvim_buf_set_lines(0, 0, -1, true, { 'one', 'two', 'three' })
|
||||
feed('<Down>')
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
th^ree |
|
||||
{0:~ }|*3
|
||||
## grid 3
|
||||
|
|
||||
## grid 4
|
||||
{1:the only line }|
|
||||
{1: }|
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 6, startcol = 0, startrow = 0, width = 40, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[4] = { 1001, 'NW', 1, 0, 0, true, 50, 1, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect { mode = 'normal' }
|
||||
end
|
||||
-- Cursor shape on a lower z-index floating window
|
||||
buf = api.nvim_create_buf(false, false)
|
||||
api.nvim_buf_set_lines(buf, 0, 0, true, { 'highest' })
|
||||
local high_win = api.nvim_open_win(buf, false, { relative = 'editor', row = 0, col = 0, height = 2, width = 7, zindex = 150 })
|
||||
api.nvim_set_current_win(win)
|
||||
api.nvim_win_set_cursor(win, { 2, 1 })
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
three |
|
||||
{0:~ }|*3
|
||||
## grid 3
|
||||
|
|
||||
## grid 4
|
||||
{1:the only line }|
|
||||
{1:^ }|
|
||||
## grid 5
|
||||
{1:highest}|
|
||||
{1: }|
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 6, startcol = 0, startrow = 0, width = 40, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[5] = { 1002, 'NW', 1, 0, 0, true, 150, 2, 0, 0 },
|
||||
[4] = { 1001, 'NW', 1, 0, 0, true, 50, 1, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect { mode = 'replace' }
|
||||
end
|
||||
|
||||
api.nvim_set_current_win(high_win)
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
three |
|
||||
{0:~ }|*3
|
||||
## grid 3
|
||||
|
|
||||
## grid 4
|
||||
{1:the only line }|
|
||||
{1: }|
|
||||
## grid 5
|
||||
{1:^highest}|
|
||||
{1: }|
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 6, startcol = 0, startrow = 0, width = 40, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[5] = { 1002, 'NW', 1, 0, 0, true, 150, 2, 0, 0 },
|
||||
[4] = { 1001, 'NW', 1, 0, 0, true, 50, 1, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1:^highesty line } |
|
||||
{1: } |
|
||||
three |
|
||||
{0:~ }|*3
|
||||
|
|
||||
]],
|
||||
mode = 'normal',
|
||||
}
|
||||
end
|
||||
|
||||
buf = api.nvim_create_buf(false, false)
|
||||
api.nvim_buf_set_lines(buf, 0, 0, true, { 'another' })
|
||||
api.nvim_open_win(buf, true, { relative = 'editor', row = 0, col = 0, height = 2, width = 7, zindex = 160 })
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:----------------------------------------]|*6
|
||||
[3:----------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
three |
|
||||
{0:~ }|*3
|
||||
## grid 3
|
||||
|
|
||||
## grid 4
|
||||
{1:the only line }|
|
||||
{1: }|
|
||||
## grid 5
|
||||
{1:highest}|
|
||||
{1: }|
|
||||
## grid 6
|
||||
{1:^another}|
|
||||
{1: }|
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 6, startcol = 0, startrow = 0, width = 40, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[4] = { 1001, 'NW', 1, 0, 0, true, 50, 1, 0, 0 },
|
||||
[5] = { 1002, 'NW', 1, 0, 0, true, 150, 2, 0, 0 },
|
||||
[6] = { 1003, 'NW', 1, 0, 0, true, 160, 3, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1:^anothery line } |
|
||||
{1: } |
|
||||
three |
|
||||
{0:~ }|*3
|
||||
|
|
||||
]],
|
||||
mode = 'normal',
|
||||
}
|
||||
end
|
||||
api.nvim_set_current_win(normal_win)
|
||||
command('only')
|
||||
screen:try_resize(50, 20)
|
||||
buf = api.nvim_create_buf(false, false)
|
||||
api.nvim_buf_set_lines(buf, 0, -1, true, { 'x' })
|
||||
local float_win = api.nvim_open_win(buf, true, {
|
||||
relative = 'editor',
|
||||
width = 5,
|
||||
height = 5,
|
||||
row = 8,
|
||||
col = 9,
|
||||
border = 'single',
|
||||
zindex = 1,
|
||||
})
|
||||
local buf2 = api.nvim_create_buf(false, false)
|
||||
api.nvim_open_win(buf2, false, {
|
||||
relative = 'editor',
|
||||
width = 10,
|
||||
height = 10,
|
||||
row = 0,
|
||||
col = 0,
|
||||
zindex = 2,
|
||||
})
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:--------------------------------------------------]|*19
|
||||
[3:--------------------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
three |
|
||||
{0:~ }|*16
|
||||
## grid 3
|
||||
|
|
||||
## grid 7
|
||||
{5:┌─────┐}|
|
||||
{5:│}{1:^x }{5:│}|
|
||||
{5:│}{2:~ }{5:│}|*4
|
||||
{5:└─────┘}|
|
||||
## grid 8
|
||||
{1: }|
|
||||
{2:~ }|*9
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 19, startcol = 0, startrow = 0, width = 50, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[7] = { 1004, 'NW', 1, 8, 9, true, 1, 1, 8, 9 },
|
||||
[8] = { 1005, 'NW', 1, 0, 0, true, 2, 2, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1: } |
|
||||
{2:~ } |*2
|
||||
{2:~ }{0: }|*5
|
||||
{2:~ }{5:─────┐}{0: }|
|
||||
{2:~ }{1:^x }{5:│}{0: }|
|
||||
{0:~ }{5:│}{2:~ }{5:│}{0: }|*4
|
||||
{0:~ }{5:└─────┘}{0: }|
|
||||
{0:~ }|*4
|
||||
|
|
||||
]],
|
||||
mode = 'normal',
|
||||
}
|
||||
end
|
||||
-- Move window
|
||||
api.nvim_win_set_config(float_win, { relative = 'editor', row = 9, col = 8 })
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:--------------------------------------------------]|*19
|
||||
[3:--------------------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
three |
|
||||
{0:~ }|*16
|
||||
## grid 3
|
||||
|
|
||||
## grid 7
|
||||
{5:┌─────┐}|
|
||||
{5:│}{1:^x }{5:│}|
|
||||
{5:│}{2:~ }{5:│}|*4
|
||||
{5:└─────┘}|
|
||||
## grid 8
|
||||
{1: }|
|
||||
{2:~ }|*9
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 19, startcol = 0, startrow = 0, width = 50, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[7] = { 1004, 'NW', 1, 9, 8, true, 1, 1, 9, 8 },
|
||||
[8] = { 1005, 'NW', 1, 0, 0, true, 2, 2, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1: } |
|
||||
{2:~ } |*2
|
||||
{2:~ }{0: }|*6
|
||||
{2:~ }{5:────┐}{0: }|
|
||||
{0:~ }{5:│}{1:^x }{5:│}{0: }|
|
||||
{0:~ }{5:│}{2:~ }{5:│}{0: }|*4
|
||||
{0:~ }{5:└─────┘}{0: }|
|
||||
{0:~ }|*3
|
||||
|
|
||||
]],
|
||||
mode = 'normal',
|
||||
}
|
||||
end
|
||||
|
||||
-- rightleft
|
||||
api.nvim_win_set_config(float_win, { relative = 'editor', row = 8, col = 8 })
|
||||
command('set rightleft')
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:--------------------------------------------------]|*19
|
||||
[3:--------------------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
three |
|
||||
{0:~ }|*16
|
||||
## grid 3
|
||||
|
|
||||
## grid 7
|
||||
{5:┌─────┐}|
|
||||
{5:│}{1: ^x}{5:│}|
|
||||
{5:│}{2: ~}{5:│}|*4
|
||||
{5:└─────┘}|
|
||||
## grid 8
|
||||
{1: }|
|
||||
{2:~ }|*9
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 19, startcol = 0, startrow = 0, width = 50, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[7] = { 1004, 'NW', 1, 8, 8, true, 1, 1, 8, 8 },
|
||||
[8] = { 1005, 'NW', 1, 0, 0, true, 2, 2, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1: } |
|
||||
{2:~ } |*2
|
||||
{2:~ }{0: }|*5
|
||||
{2:~ }{5:────┐}{0: }|
|
||||
{2:~ }{1: ^x}{5:│}{0: }|
|
||||
{0:~ }{5:│}{2: ~}{5:│}{0: }|*4
|
||||
{0:~ }{5:└─────┘}{0: }|
|
||||
{0:~ }|*4
|
||||
|
|
||||
]],
|
||||
mode = 'normal',
|
||||
}
|
||||
end
|
||||
|
||||
command('set virtualedit=all')
|
||||
fn.setpos('.', { 0, 1, 1, 4 })
|
||||
if multigrid then
|
||||
screen:expect({
|
||||
grid = [[
|
||||
## grid 1
|
||||
[2:--------------------------------------------------]|*19
|
||||
[3:--------------------------------------------------]|
|
||||
## grid 2
|
||||
one |
|
||||
two |
|
||||
three |
|
||||
{0:~ }|*16
|
||||
## grid 3
|
||||
|
|
||||
## grid 7
|
||||
{5:┌─────┐}|
|
||||
{5:│}{1:^ x}{5:│}|
|
||||
{5:│}{2: ~}{5:│}|*4
|
||||
{5:└─────┘}|
|
||||
## grid 8
|
||||
{1: }|
|
||||
{2:~ }|*9
|
||||
]],
|
||||
win_pos = {
|
||||
[2] = { height = 19, startcol = 0, startrow = 0, width = 50, win = 1000 },
|
||||
},
|
||||
float_pos = {
|
||||
[7] = { 1004, 'NW', 1, 8, 8, true, 1, 1, 8, 8 },
|
||||
[8] = { 1005, 'NW', 1, 0, 0, true, 2, 2, 0, 0 },
|
||||
},
|
||||
mode = 'normal',
|
||||
})
|
||||
else
|
||||
screen:expect { mode = 'replace' }
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
describe('with ext_multigrid and actual mouse grid', function()
|
||||
|
||||
Reference in New Issue
Block a user