]> git.ipfire.org Git - thirdparty/vim.git/commit
patch 9.2.0469: popup: textprop-anchored popups bleed past host window edges v9.2.0469
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Sun, 10 May 2026 18:53:57 +0000 (18:53 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 10 May 2026 19:02:38 +0000 (19:02 +0000)
commite3d9929109dadef35624ea7a68a6dbf0ca013f46
tree0247f748195e19a9c7266015863702b7d2ce795f
parentef1ecc3b61fd9f462ae3571ed98dd09457659e63
patch 9.2.0469: popup: textprop-anchored popups bleed past host window edges

Problem:  A popup anchored to a text property in a split window is
          positioned relative to the screen and may extend into
          adjacent splits or off-screen regions.  There is no way to
          confine the popup to the window that contains the textprop.
Solution: Add the "clipwindow" popup option to allow clipping the text
          property popup to the host window (Yasuhiro Matsumoto).

Adds a "clipwindow" boolean option to popup_create()/popup_setoptions().
When set on a textprop-anchored popup, the popup's drawn extent is
confined to its host (textprop) window's content rectangle so the popup
no longer bleeds across a horizontal split's statusline (top/bottom) or
a vsplit's separator (right) into another window.

The popup keeps its full logical size and position; only the rows or
columns that fall outside the host window's content area are skipped
during drawing, so a popup that scrolls toward the host's edge looks
visually "cut off" without its borders being relocated.  popup_getoptions
and popup_getpos continue to report the unclipped geometry.

Implementation:

  - w_popup_topoff / w_popup_bottomoff record how many rows of the
    popup fall outside the host on each side.  popup_adjust_position()
    computes them from the host rectangle after the logical layout is
    finalised, and update_popups() and the popup-mask builder subtract
    them when emitting cells/borders/scrollbar and when marking
    popup-owned cells.  win_update() is bracketed by transient
    w_height/w_topline/w_winrow adjustments so the buffer's drawn
    content matches the visible row range.

  - w_popup_rightclip is the horizontal counterpart for the host's
    right edge: the right border, padding and content columns past
    the host are not drawn.  win_update() is bracketed by a transient
    w_width reduction so the buffer text is not written past the
    host's right edge either.

  - When the textprop scrolls just above the host window's top, the
    popup is kept visible by extending the prop search above topline
    (new helper find_prop_in_lines) and synthesising a negative
    screen_row so the top-clip path can roll the popup off the top.
    When the textprop has scrolled far enough that even the bottom
    border would overlap the host edge -- or when the popup would
    overflow the host's left edge at all -- the popup is hidden, and
    unhidden again once it comes back within range.

  - The "reduce-height" / "clamp winrow to 0" fallbacks in
    popup_adjust_position are bypassed for host-clipped popups so the
    popup keeps its natural anchored position instead of being
    snapped to the screen edge.

    Left-edge partial clipping is intentionally not supported: it
    would require shrinking the buffer width during win_update, which
    reflows wrapped lines and corrupts the displayed content; the
    popup is hidden instead.

closes: #20166

Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
15 files changed:
runtime/doc/popup.txt
runtime/doc/tags
runtime/doc/version9.txt
src/popupwin.c
src/proto/textprop.pro
src/structs.h
src/testdir/dumps/Test_popup_clipwindow_bottom_clip.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_clipwindow_hidden.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_clipwindow_left_clip.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_clipwindow_right_clip.dump [new file with mode: 0644]
src/testdir/dumps/Test_popup_clipwindow_top_clip.dump [new file with mode: 0644]
src/testdir/test_popupwin.vim
src/textprop.c
src/version.c
src/vim.h