Skip to content

fix(proxy,llm): scroll shell content up when inline panel opens at the bottom#99

Open
fentas wants to merge 3 commits into
masterfrom
fix/inline-panel-push-prompt-up
Open

fix(proxy,llm): scroll shell content up when inline panel opens at the bottom#99
fentas wants to merge 3 commits into
masterfrom
fix/inline-panel-push-prompt-up

Conversation

@fentas
Copy link
Copy Markdown
Owner

@fentas fentas commented May 18, 2026

Summary

Bug: prompt at the bottom row of the terminal. Press Alt+C → panel opens but the prompt isn't pushed above the new reservation; it stays in its original row, now inside (and over-painted by) the chat panel zone. Ctrl+Up (focus park) then lands the cursor inside the panel — invisible.

Two coordinated changes:

  1. proxy.zig — when the reservation GROWS and the cursor sits below the new bottom-of-scroll-region, emit `\n` × delta at the OLD bottom of the scroll region. Each newline at the bottom of DECSTBM triggers a scroll-up of the visible content, so the prompt moves UP by delta rows. Then explicitly CUP the cursor to its new visual row. The bytes are also fed through the cursor tracker so subsequent state stays consistent.

  2. modules/llm/hooks.zig + paint.zig — `chat_open_cursor_row` used to be captured at the toggle-action handler. With the proxy now scrolling between action dispatch and the next paint, that pre-scroll row is stale. Defer the capture to the first paint after open (sentinel: snapshot=0 means "not captured yet"). `ctx.cursor_row` by paint time reflects the post-scroll position, so the captured value is correct AND `inlineRestoreRow` lands the cursor on the actual prompt row.

Four existing paint tests that pinned "snapshot captured at action time" updated to the new lazy-capture timing — the observable invariant (cursor lands at the right row after paint) is unchanged.

Test plan

  • `zig build test` — 589 pass
  • `zig build -Dtarget=x86_64-linux-gnu` clean
  • `zig fmt --check src/` clean
  • Manual on Ghostty: scroll to bottom of terminal, prompt at last row of shell area, Alt+C → panel opens, prompt visibly scrolls up above the panel
  • Manual: Alt+C in a non-bottom prompt position (mid-screen) — no over-scroll (delta is bounded by cursor_row - new_bottom)
  • Manual: Ctrl+Up while panel is open → cursor parks on the prompt (not invisibly inside the panel)

🤖 Generated with Claude Code

fentas and others added 3 commits May 18, 2026 19:22
…e bottom

Reported: prompt at the bottom row of the terminal. Press Alt+C →
panel opens but the prompt isn't pushed above the new reservation;
it stays in its original row, now inside (and over-painted by) the
chat panel zone. Ctrl+Up (focus park) then lands the cursor inside
the panel — invisible.

Two coordinated changes:

1. **proxy.zig** — when the reservation GROWS and the cursor sits
   below the new bottom-of-scroll-region, emit `\n` × delta at the
   OLD bottom of the scroll region. Each newline at the bottom of
   DECSTBM triggers a scroll-up of the visible content, so the
   prompt moves UP by delta rows. Then explicitly CUP the cursor to
   its new visual row. The bytes are also fed through the cursor
   tracker so subsequent state stays consistent.

2. **modules/llm/hooks.zig + paint.zig** — `chat_open_cursor_row`
   used to be captured at the toggle-action handler. With the
   proxy now scrolling between action dispatch and the next paint,
   that pre-scroll row is stale. Defer the capture to the first
   paint after open (sentinel: snapshot=0 means "not captured
   yet"). `ctx.cursor_row` by paint time reflects the post-scroll
   position, so the captured value is correct AND
   `inlineRestoreRow` lands the cursor on the actual prompt row.

The four existing paint tests that pinned "snapshot captured at
action time" updated to the new lazy-capture timing — the
observable invariant (cursor lands at the right row after paint)
is unchanged; only the timing differs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The prior scroll-up landed the prompt at the new bottom of the
shell scroll region — directly adjacent to the panel's first row.
Visually the panel chrome hugged the prompt. Target one row above
the new bottom instead so a blank line sits between them.

Also gate the trigger on `cur_row > target_row` (was `>
new_bottom`) so the gap is enforced even when the prompt is
already at the row that USED to be the target.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tice

The scroll-up approach (`\n` × delta at OLD bottom of DECSTBM
region) produced a broken layout in real usage: chat panel ended
up mid-screen with shell content above AND below, prompt
duplicating across rows. Theoretical model didn't match what the
terminal + bash actually do under SIGWINCH + DECSTBM transition.

Keeping the LAZY chat_open_cursor_row capture from the same PR —
that's safe in isolation (just moves the snapshot from action-
fire time to first-paint, observable behaviour unchanged) and is
a precondition for any future fix that scrolls between action
dispatch and paint.

The original bug (prompt at bottom row gets over-painted by the
panel on Alt+C) is still open. Need a different approach.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant