patch 9.2.0230: popup: opacity not working accross vert splits

Commit: 
https://github.com/vim/vim/commit/196cf9f644b39b9c2b742b271d5d78e9bb31745c
Author: Yasuhiro Matsumoto <[email protected]>
Date:   Sun Mar 22 20:38:22 2026 +0000

    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 <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/src/popupwin.c b/src/popupwin.c
index fe06777f7..ed6f6fc1b 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 000000000..f67209056
--- /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 000000000..cf2f42681
--- /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 41cd6f0d0..ab6a74d07 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 fd702323c..cfd6d0657 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,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1w4PfT-000yKM-BX%40256bit.org.

Raspunde prin e-mail lui