Skip to content

fix(renderer): only take the statusline off a window's bottom once - #384

Open
yal212 wants to merge 1 commit into
3rd:masterfrom
yal212:fix/laststatus-bottom-row
Open

yal212 wants to merge 1 commit into
3rd:masterfrom
yal212:fix/laststatus-bottom-row

Conversation

@yal212

@yal212 yal212 commented Sep 24, 2026

Copy link
Copy Markdown

Fixes #383.

With laststatus=2, a normal window never showed an image in its last row. An image whose top was on that row was sent with a crop height of 0, which the kitty protocol reads as the whole image, so it was drawn over the statusline and command line. laststatus=0 and 3 were fine.

Cause

Two terms applied only when laststatus == 2:

  • get_windows() took a row off rect.bottom for the statusline, but nvim_win_get_height() already excludes it. The renderer's bounds.bottom - 1, which turns the exclusive bottom into the last row, then counted that row a second time.
  • is_below added the row back (+ laststatus_offset), so an image one row below the bounds still counted as visible and was cropped to (bounds.bottom - y + 1) = 0 rows.

Change

  • lua/image/utils/window.lua: rect.bottom = rect_top + content_height for every laststatus. This also makes the float-overlap masks, which already treat rect.bottom as exclusive, correct for the last row.
  • lua/image/renderer.lua: is_below = absolute_y > bounds.bottom, with the now-unused laststatus_offset removed. The renderer's - 1 stays.

Fixing only window.lua would bring back the statusline overdraw, because is_below would still let an image that starts on the statusline row through. One of the new tests covers that.

Tests

  • tests/utils/window_spec.lua: a normal window's rect.bottom is top + height for laststatus 0, 2 and 3.
  • tests/renderer/bottom_bounds_spec.lua: in a real window, a 3-row image whose top is on the window's third-to-last, second-to-last and last row is shown with 3, 2 and 1 rows, and one that starts below the window is not rendered, for laststatus 0, 2 and 3.

Without the fix, the laststatus=2 cases fail (2 rows instead of 3, and rect.bottom 19 instead of 20). With it, the full suite passes (103/103, busted + nlua on Lua 5.1, as in CI).

Verified live

This is the repro from #383, kitty backend, Ghostty inside tmux. display_height is in rows at 32 px cells:

laststatus master this PR
0 3, 2, 1 3, 2, 1
2 2, 1, 0 3, 2, 1
3 3, 2, 1 3, 2, 1

Both laststatus terms came from #180 (for #179, an image over the statusline with laststatus=2). The renderer's - 1 already keeps images off the statusline, and the last-row case above shows it: the image there is drawn 1 row tall, not over the statusline.

With laststatus=2, a normal window never showed an image in its last row,
and an image whose top was on that row was sent with a crop height of 0,
which the kitty protocol reads as the whole image, so it was drawn over
the statusline and the command line.

get_windows() took a row off rect.bottom for the statusline, but
nvim_win_get_height() already excludes it. The renderer's own
bounds.bottom - 1 then turned that into the second-to-last row, and the
out-of-bounds check added laststatus_offset back, so an image one row
below the bounds still counted as visible and was cropped to 0 rows.

rect.bottom is now top + height for every laststatus, and is_below
compares against the bounds alone.

Fixes 3rd#383
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

With laststatus=2, a window's last row never shows an image, and an image starting there is drawn over the statusline

1 participant