]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.2.0765: popup: opacity popup over a terminal is not cleared when moved v9.2.0765
authorHirohito Higashi <h.east.727@gmail.com>
Thu, 2 Jul 2026 17:59:24 +0000 (17:59 +0000)
committerChristian Brabandt <cb@256bit.org>
Thu, 2 Jul 2026 17:59:24 +0000 (17:59 +0000)
Problem:  A semi-transparent (opacity) popup shown over a terminal window
          leaves its old cells on screen when it is moved or its text
          changes, and typing in the terminal makes them accumulate.  Only
          a full redraw (CTRL-L) clears them.
Solution: When redrawing the background under an opacity popup, force a full
          repaint of an underlying terminal window so the blend uses the
          terminal's true background instead of stale, already-blended
          cells.

fixes:  #20679
closes: #20688

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/popupwin.c
src/testdir/dumps/Test_popupwin_opacity_term_move_1.dump [new file with mode: 0644]
src/testdir/dumps/Test_popupwin_opacity_term_move_2.dump [new file with mode: 0644]
src/testdir/test_popupwin.vim
src/version.c

index 849849f8279076e9648be31fd80d7028339bd4d4..96fa7895a1babe8af6ad91d343519e33ffd75900 100644 (file)
@@ -6132,7 +6132,7 @@ redraw_win_under_opacity_popup(win_T *wp)
        // 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)
+               col < wp->w_wincol + width && col < screen_Columns; ++col)
        {
            int     line_cp = r;
            int     col_cp = col;
@@ -6146,10 +6146,21 @@ redraw_win_under_opacity_popup(win_T *wp)
                {
                    linenr_T lnum;
 
-                   (void)mouse_comp_pos(twp, &line_cp, &col_cp, &lnum, NULL);
-                   // Called from inside update_screen(); raising must_redraw
-                   // would loop the outer redraw indefinitely.
-                   redraw_win_range_now(twp, lnum, lnum);
+#ifdef FEAT_TERMINAL
+                   // A terminal only repaints vterm-damaged rows; force a
+                   // full repaint so the opacity blend sees the true
+                   // background, not stale blended cells.
+                   if (term_do_update_window(twp))
+                       twp->w_redr_type = UPD_NOT_VALID;
+                   else
+#endif
+                   {
+                       (void)mouse_comp_pos(twp, &line_cp, &col_cp, &lnum,
+                                                                       NULL);
+                       // Called from inside update_screen(); raising
+                       // must_redraw would loop the outer redraw indefinitely.
+                       redraw_win_range_now(twp, lnum, lnum);
+                   }
                }
                else if (line_cp == twp->w_height)
                    // Status bar line: mark for redraw to prevent
diff --git a/src/testdir/dumps/Test_popupwin_opacity_term_move_1.dump b/src/testdir/dumps/Test_popupwin_opacity_term_move_1.dump
new file mode 100644 (file)
index 0000000..46714d0
--- /dev/null
@@ -0,0 +1,12 @@
+|v+0&#ffffff0|i|m|>| > @69
+@75
+@75
+@75
+@9|A+0#0000001#ffffff255|B|C| +0#0000000#ffffff0@62
+@75
+@75
+@75
+@75
+@75
+@75
+@75
diff --git a/src/testdir/dumps/Test_popupwin_opacity_term_move_2.dump b/src/testdir/dumps/Test_popupwin_opacity_term_move_2.dump
new file mode 100644 (file)
index 0000000..9a9b0f5
--- /dev/null
@@ -0,0 +1,12 @@
+|v+0&#ffffff0|i|m|>| > @69
+@75
+@75
+@75
+@12|X+0#0000001#ffffff255|Y|Z| +0#0000000#ffffff0@59
+@75
+@75
+@75
+@75
+@75
+@75
+|:|c|a|l@1| |M|o|v|e|I|t|(|)| @60
index 79f8dac39bf193484e49e2dab93772e1ac199ffc..5e4bc5221fd5fe28591e9748c576cdb3aa241cfb 100644 (file)
@@ -5315,6 +5315,43 @@ func Test_popup_opacity_settext_no_leftover()
   call StopVimInTerminal(buf)
 endfunc
 
+func Test_popup_opacity_terminal_move_no_leftover()
+  CheckScreendump
+  CheckFeature terminal
+  CheckUnix
+
+  " A semi-transparent popup over a terminal used to leave the old popup
+  " cells behind when it moved.
+  let lines =<< trim END
+    set shell=/bin/sh noruler
+    unlet $PROMPT_COMMAND
+    let $PS1 = 'vim> '
+    terminal ++curwin
+    call popup_create('ABC',
+        \ #{line: 5, col: 10, highlight: 'None', opacity: 30})
+    func MoveIt()
+      let id = popup_list()[0]
+      call popup_settext(id, 'XYZ')
+      call popup_setoptions(id, #{col: popup_getpos(id).col + 3})
+    endfunc
+  END
+  call writefile(lines, 'XtestPopupOpacityTermMove', 'D')
+  let buf = RunVimInTerminal('-S XtestPopupOpacityTermMove',
+       \ #{rows: 12, wait_for_ruler: 0})
+  call WaitForAssert({-> assert_match('ABC', term_getline(buf, 5))})
+  call VerifyScreenDump(buf, 'Test_popupwin_opacity_term_move_1', {})
+
+  " Move the popup and change its text: the old "ABC" cells must be cleared.
+  call term_sendkeys(buf, "\<C-W>:call MoveIt()\<CR>")
+  call WaitForAssert({-> assert_match('XYZ', term_getline(buf, 5))})
+  call VerifyScreenDump(buf, 'Test_popupwin_opacity_term_move_2', {})
+
+  " clean up
+  call term_sendkeys(buf, "\<C-W>:qa!\<CR>")
+  call WaitForAssert({-> assert_equal("finished", term_getstatus(buf))})
+  exe buf .. 'bwipe!'
+endfunc
+
 func Test_popup_opacity_terminal_no_freeze()
   CheckFeature terminal
   CheckUnix
index 09f4dc2c4766f84c88534b03a17826c29acb06a0..dd14dedba2aa772a7618a7182033713b7d5e6aae 100644 (file)
@@ -759,6 +759,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    765,
 /**/
     764,
 /**/