This brings the terminal element's viewport culling in line with the
editor optimization in PR #44995 and the fix in PR #45077.
## Problem
When a terminal is inside a scrollable container (e.g., the Agent Panel
thread view), it would render ALL cells during prepaint, even when the
terminal was entirely outside the viewport. This caused unnecessary CPU
usage when multiple terminal tool outputs existed in the Agent Panel.
## Solution
Calculate the intersection of the terminal's bounds with the current
content_mask (the visible viewport after all parent clipping). If the
intersection has zero area, skip all cell processing entirely.
### Three code paths
1. **Offscreen** (`intersection.size <= 0`): Early exit, process 0 cells
2. **Fully visible** (`intersection == bounds`): Fast path, stream cells
directly (no allocation)
3. **Partially clipped**: Group cells by line, skip/take visible rows
only
### Key insight: filter by screen position, not buffer coordinates
The previous approach tried to filter cells by `cell.point.line`
(terminal buffer coordinates), which breaks in Scrollable mode where
cells can have negative line numbers for scrollback history.
The new approach filters by **screen position** using
`chunk_by(line).skip(N).take(M)`, which works regardless of the actual
line numbers because we're filtering on enumerated line group index.
## Testing
Added comprehensive unit tests for:
- Screen-position filtering with positive lines (Inline mode)
- Screen-position filtering with negative lines (Scrollable mode with
scrollback)
- Edge cases (skip all, positioning math)
- Unified filtering works for both modes
Manually verified:
- Terminal fully visible (no clipping) ✓
- Terminal clipped from top/bottom ✓
- Terminal completely outside viewport ✓
- Scrollable terminals with scrollback history ✓
- Selection/interaction still works ✓
Release Notes:
- Improved Agent Panel performance when terminals are scrolled
offscreen.
/cc @as-cii