commit 0712a9c87bfe1ce08ae95a0cb30e5857c28e861c
parent a9271f927ff60cadf91bb17286698ceb26eeaa44
Author: glepnir <glephunter@gmail.com>
Date: Tue, 20 Jan 2026 11:39:48 +0800
fix(pum): separate scrollbar from shadow border (#37448)
Problem:
With shadow border, scrollbar and border overlap. Shadow's right border
starts from the second row (offset by 1), but scrollbar renders on every
row including the first. If they share a column, the first row shows
scrollbar where shadow hasn't started yet, causing misalignment.
Solution:
Separate scrollbar from the shadow's right border.
Diffstat:
2 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
@@ -643,7 +643,7 @@ void pum_redraw(void)
}
}
- if (pum_scrollbar > 0 && !fconfig.border) {
+ if (pum_scrollbar > 0 && (!fconfig.border || fconfig.shadow)) {
grid_width++;
if (pum_rl) {
col_off++;
@@ -917,8 +917,10 @@ void pum_redraw(void)
if (pum_scrollbar > 0) {
bool thumb = i >= thumb_pos && i < thumb_pos + thumb_height;
int scrollbar_col = col_off + (pum_rl ? -pum_width : pum_width);
- grid_line_put_schar(scrollbar_col, (has_border && !thumb) ? border_char : fill_char,
- thumb ? attr_thumb : (has_border ? border_attr : attr_scroll));
+ bool use_border_style = has_border && !fconfig.shadow;
+ grid_line_put_schar(scrollbar_col,
+ (use_border_style && !thumb) ? border_char : fill_char,
+ thumb ? attr_thumb : (use_border_style ? border_attr : attr_scroll));
}
grid_line_flush();
row++;
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
@@ -9286,6 +9286,57 @@ describe('builtin popupmenu', function()
{5:-- }{6:match 1 of 3} |
]])
end
+ command('set pumheight=2')
+ feed('<C-x><C-O>')
+ if multigrid then
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:------------------------------]|*10
+ [3:------------------------------]|
+ ## grid 2
+ oneone^ |
+ line1 |
+ line2line2line2line2 |
+ line3 |
+ line4line4line4 |
+ line5line5 |
+ {1:~ }|*4
+ ## grid 3
+ {5:-- }{6:match 1 of 3} |
+ ## grid 4
+ {n:1info}|
+ ## grid 5
+ {12: one }{c: }{114: }|
+ {n: two }{12: }{115: }|
+ {114: }{115: }|
+ ]],
+ win_pos = {
+ [2] = {
+ height = 10,
+ startcol = 0,
+ startrow = 0,
+ width = 30,
+ win = 1000,
+ },
+ },
+ float_pos = {
+ [5] = { -1, 'NW', 2, 1, 2, false, 100, 2, 1, 2 },
+ [4] = { 1001, 'NW', 1, 1, 19, false, 50, 1, 1, 19 },
+ },
+ })
+ else
+ screen:expect([[
+ oneone^ |
+ li{12: one }{c: }{116: }{n:info} |
+ li{n: two }{12: }{117:2} |
+ li{116:n}{117:e3 } |
+ line4line4line4 |
+ line5line5 |
+ {1:~ }|*4
+ {5:-- }{6:match 1 of 3} |
+ ]])
+ end
end)
it("'pumborder' with none #36207", function()
command('set wildoptions=pum pumborder=none')