Skip to content

fix: zoom tears on a tall scroll region; terminal cursor follows the zoomed program - #141

Merged
cmj0121 merged 4 commits into
mainfrom
fix/zoom-margins-cursor
Sep 30, 2026
Merged

cmj0121 merged 4 commits into
mainfrom
fix/zoom-margins-cursor

Conversation

@cmj0121

@cmj0121 cmj0121 commented Sep 30, 2026

Copy link
Copy Markdown
Owner

What

Three fixes to the zoom, from investigating #139 and #140.

  • Clamp DECSTBM to the emulator's height (internal/vtirm). The daemon log holds 539 recovered an emulator write panic entries since June, every one in ultraviolet.(*Buffer).DeleteLineArea via vt.(*Screen).DeleteLine. Reproduced: a CSI 1;50 r on a 24-row emulator leaves the scroll region larger than the buffer, and the next DL / IL / RI / SU / SD indexes past it. The recover drops the rest of the chunk, so the panel shows a torn screen until the next full repaint. A program asks for such a margin whenever it still believes an older, taller PTY size, the window every zoom passes through between its attach and its resize. Upstream (x/vt 2026-09-27, ultraviolet 2026-09-29) does not clamp either, so the filter that already rewrites IRM now clamps margins on the way in, as a real terminal does.
  • The terminal cursor follows the zoomed program (tea.View.Cursor). The zoom painted a reverse-video cell and left the real cursor at the end of the footer, which is where an input method draws the text it is composing: CJK marked text there wraps the line and scrolls the alternate screen out from under the diff renderer, for claude and grok alike. Verified end to end: with a real daemon on a private socket and a real grok panel, the terminal cursor now sits on grok's prompt cell (and advances four cells for 中文) where it used to sit on the footer.
  • clipVisible clips by cell. A scrollback line of wide glyphs captured at a wider size was clipped by rune count and could overflow its tile by up to twice its width.

Verified not the cause

The emulator renders grok's frames (truecolor per-cell backgrounds, ?2026 synchronized output, SGR 59, braille art) identically to a reference at 80x24 and after a 120x40 resize; the replay+resize path from #133 reproduces the reference from any ring cut; an end-to-end cockpit run with a real grok panel rendered correctly before the change.

Tests

  • vtirm: table of DECSTBM rewrites, no clamp without Rows, a sequence split across chunks.
  • tui: every line op after a too-tall margin keeps the bytes that follow it; an in-range region still scrolls as asked; View().Cursor follows the emulator (wide glyphs included) and is withheld in history, selection, input overlays, the dashboard, and a too-small cockpit; clipVisible on CJK; golden zoom frames regenerated (only the painted cursor cell changed).
  • make ci green locally.

Deferred

Interact mode in a group split still composes wherever the renderer left the cursor; several tiles share one terminal cursor, so that needs its own design.

Closes #139
Closes #140

    A program that still believes an older, taller PTY size sets margins past
    the emulator's last row; the emulator stores them as asked, and the next
    DL / IL / RI / SU / SD indexes past its buffer and panics. writeEmu's
    recover drops the rest of that chunk, so the panel shows a torn screen
    until the program's next full repaint. The daemon log holds 539 of these
    since June, every one in DeleteLineArea. Every zoom passes through the
    window that provokes it, between its attach and its resize.

    The filter that already rewrites IRM now clamps DECSTBM on the way in,
    the way a real terminal does: bottom pinned to the last row, a region
    that ends up under two rows dropped, as xterm ignores it. writeEmu tells
    the filter the emulator's height on every write, so a resized emulator
    clamps to its new size.

    Closes #139
    The zoom painted a reverse-video cell where the program's cursor was and
    left the terminal's own cursor wherever the renderer last wrote, the end
    of the footer. That is where an input method draws the text it is
    composing: CJK marked text there wrapped the line and scrolled the
    alternate screen out from under the diff renderer, for claude and grok
    alike. A real terminal composes at the program's cursor.

    View now reports the emulator's cursor through tea.View.Cursor while the
    zoom is at its live bottom with the cursor visible, and withholds it in
    history, during a copy selection, under a text-input overlay, or when
    the program hid it. The painted cell goes; the group tiles keep theirs,
    there being one terminal cursor for several tiles. Golden zoom frames
    regenerated: the only change is the painted cell.

    Closes #140
    clipVisible counted every rune as one column, so a scrollback line of
    wide glyphs captured at a wider size came back up to twice the tile's
    width and wrapped in it. It now counts display cells and drops a wide
    glyph that would straddle the cut.
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 92.59259% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.36%. Comparing base (e3d66dc) to head (0417daa).

Files with missing lines Patch % Lines
internal/tui/tui.go 81.81% 1 Missing and 1 partial ⚠️
internal/vtirm/vtirm.go 94.59% 1 Missing and 1 partial ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #141   +/-   ##
=======================================
  Coverage   88.35%   88.36%           
=======================================
  Files         149      149           
  Lines       23219    23266   +47     
=======================================
+ Hits        20516    20559   +43     
- Misses       1912     1913    +1     
- Partials      791      794    +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@cmj0121
cmj0121 merged commit e1459c2 into main Sep 30, 2026
2 checks passed
@cmj0121
cmj0121 deleted the fix/zoom-margins-cursor branch September 30, 2026 03:14
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.

zoom: selecting a word while typing CJK breaks the UI (claude and grok) zoom: grok panel does not render correctly

2 participants