From: Yasuhiro Matsumoto Date: Sun, 22 Mar 2026 20:38:22 +0000 (+0000) Subject: patch 9.2.0230: popup: opacity not working accross vert splits X-Git-Tag: v9.2.0230^0 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=196cf9f644b39b9c2b742b271d5d78e9bb31745c;p=thirdparty%2Fvim.git patch 9.2.0230: popup: opacity not working accross vert splits Problem: popup: opacity not working across vert splits Solution: Iterate over the full popup width to find all underlying windows (Yasuhiro Matsumoto) redraw_win_under_opacity_popup() only checked the popup's left column to find underlying windows. When a popup spans a vertical split, the right-side window was never forced to redraw, causing blended ScreenAttrs values to accumulate across redraw cycles. Iterate across the full popup width to find and redraw all underlying windows. closes: #19737 Signed-off-by: Yasuhiro Matsumoto Signed-off-by: Christian Brabandt --- diff --git a/src/popupwin.c b/src/popupwin.c index fe06777f7c..ed6f6fc1bb 100644 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -4298,6 +4298,7 @@ popup_mark_opacity_zindex(win_T *wp) redraw_win_under_opacity_popup(win_T *wp) { int height; + int width; int r; if (!(wp->w_popup_flags & POPF_OPACITY) || wp->w_popup_blend <= 0 @@ -4305,27 +4306,38 @@ redraw_win_under_opacity_popup(win_T *wp) return; height = popup_height(wp); + width = popup_width(wp); for (r = wp->w_winrow; r < wp->w_winrow + height && r < screen_Rows; ++r) { - int line_cp = r; - int col_cp = wp->w_wincol; - win_T *twp; + int col; + win_T *prev_twp = NULL; - twp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP); - if (twp != NULL) + // Check across the full width of the popup to find all underlying + // windows (e.g., when the popup spans a vertical split). + for (col = wp->w_wincol; + col < wp->w_wincol + width && col < screen_Columns; ++col) { - if (line_cp < twp->w_height) + int line_cp = r; + int col_cp = col; + win_T *twp; + + twp = mouse_find_win(&line_cp, &col_cp, IGNORE_POPUP); + if (twp != NULL && twp != prev_twp) { - linenr_T lnum; + prev_twp = twp; + if (line_cp < twp->w_height) + { + linenr_T lnum; - (void)mouse_comp_pos(twp, &line_cp, &col_cp, &lnum, NULL); - redrawWinline(twp, lnum); + (void)mouse_comp_pos(twp, &line_cp, &col_cp, &lnum, NULL); + redrawWinline(twp, lnum); + } + else if (line_cp == twp->w_height) + // Status bar line: mark for redraw to prevent + // opacity blend accumulation. + twp->w_redr_status = TRUE; } - else if (line_cp == twp->w_height) - // Status bar line: mark for redraw to prevent - // opacity blend accumulation. - twp->w_redr_status = TRUE; } } } diff --git a/src/testdir/dumps/Test_popupwin_opacity_vsplit_1.dump b/src/testdir/dumps/Test_popupwin_opacity_vsplit_1.dump new file mode 100644 index 0000000000..f672090567 --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_opacity_vsplit_1.dump @@ -0,0 +1,12 @@ +>r+0&#ffffff0|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @1|o|p|a|c|i|t|y| |o|v|e|r+1&&|l+0&&|v|s|p|l|i|t|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @8|1|,|1| @11|A|l@1| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +| +0&&@77 diff --git a/src/testdir/dumps/Test_popupwin_opacity_vsplit_2.dump b/src/testdir/dumps/Test_popupwin_opacity_vsplit_2.dump new file mode 100644 index 0000000000..cf2f42681f --- /dev/null +++ b/src/testdir/dumps/Test_popupwin_opacity_vsplit_2.dump @@ -0,0 +1,12 @@ +|r+0&#ffffff0|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @1|o|p|a|c|i|t|y| |o|v|e|r+1&&|l+0&&|v|s|p|l|i|t|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +>r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|r|i|g|h|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @12||+1&&|l+0&&|e|f|t| |w|i|n|d|o|w| |t|e|x|t| |h|e|r|e| |x@3| @10 +|[+3&&|N|o| |N|a|m|e|]| |[|+|]| @8|6|,|1| @11|A|l@1| |[+1&&|N|o| |N|a|m|e|]| |[|+|]| @5|1|,|1| @11|A|l@1 +| +0&&@77 diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index 41cd6f0d0f..ab6a74d077 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -4985,4 +4985,44 @@ func Test_popup_conceal_wrap() call StopVimInTerminal(buf) endfunc +func Test_popup_opacity_vsplit() + CheckScreendump + + " Opacity popup spanning a vertical split should redraw both windows + " underneath, not just the left one (blend accumulation bug). + let lines =<< trim END + call setline(1, repeat(['left window text here xxxx'], 10)) + vnew + call setline(1, repeat(['right window text here xxxx'], 10)) + wincmd h + hi PopupColor guibg=darkblue guifg=white + let g:pop_id = popup_create(['opacity over vsplit'], #{ + \ line: 3, col: 30, + \ minwidth: 25, + \ highlight: 'PopupColor', + \ opacity: 50, + \ zindex: 50, + \}) + END + call writefile(lines, 'XtestPopupOpacityVsplit', 'D') + let buf = RunVimInTerminal('-S XtestPopupOpacityVsplit', #{rows: 12, cols: 80}) + call VerifyScreenDump(buf, 'Test_popupwin_opacity_vsplit_1', {}) + + " Move cursor multiple times to trigger redraws; without the fix the + " right-side window blend accumulates on each redraw cycle. + call term_sendkeys(buf, "j") + call TermWait(buf, 50) + call term_sendkeys(buf, "j") + call TermWait(buf, 50) + call term_sendkeys(buf, "j") + call TermWait(buf, 50) + call term_sendkeys(buf, "j") + call TermWait(buf, 50) + call term_sendkeys(buf, "j") + call TermWait(buf, 50) + call VerifyScreenDump(buf, 'Test_popupwin_opacity_vsplit_2', {}) + + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 diff --git a/src/version.c b/src/version.c index fd702323c1..cfd6d06570 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 230, /**/ 229, /**/