mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-10 01:09:43 +02:00
fix(tiles): page a hollow tile only from the live screen, review follow-up
A tile counts as hollow when every row above its screen is its own overflow (baseY minus _overflowRows is 0), so unlike the primary pane, whose hollow buffer has baseY 0, its viewport can sit above the bottom while it is hollow: Shift+PageUp, a scrollbar drag or a wheel during the first replay leave it up there. _maybePageCliTranscript never looked at the viewport, so every wheel, wheel-down included, was turned into PageUp/PageDown and swallowed. xterm never scrolled back, the stale rows stayed on screen while the CLI paged out of view, and clicks were dropped too, because the click report refuses an off-bottom viewport. The tile now pages only while _terminalViewportAtBottom holds for its own terminal, checked before the pending travel is touched. Off the bottom the wheel stays with xterm, so a wheel-down brings the viewport home and paging resumes from there. The primary pane is unchanged: its hollow test already implies a viewport at the bottom, which the twin comment now says. Tests: a unit case for a tile hollow by the discount with its viewport above the bottom (no page key, no preventDefault, and no travel carried over once back home), and the real-browser case now scrolls a hollow tile up and proves a real wheel-down scrolls xterm home with no page key sent, then pages again. Both go red with the gate removed, and the unit case also with the gate moved below the pending-travel update. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -451,6 +451,38 @@ describe('rows the tile pushed above the screen itself are not history', () => {
|
||||
expect(flushed(ws)).toEqual([]);
|
||||
});
|
||||
|
||||
it('leaves the wheel to xterm while the viewport sits in those rows, and pages again from the bottom', async () => {
|
||||
// Hollow by the discount alone: baseY > 0, every row above the screen the
|
||||
// tile's own. Shift+PageUp, a scrollbar drag or a wheel during the replay
|
||||
// can leave the viewport up there; a primary hollow buffer (baseY 0) never
|
||||
// can. Paging from there would swallow every wheel and keep the stale rows
|
||||
// on screen, so xterm gets the wheel and a wheel-down brings it home.
|
||||
serveCapture(lines(40), 40);
|
||||
const { tile, ws, term, mount } = await connectTile(makeApp({ 's-tile': { mode: 'opencode' } }));
|
||||
const baseY = term.buffer.active.baseY;
|
||||
expect(baseY).toBe(16);
|
||||
expect((tile as unknown as { _localRows(): number })._localRows()).toBe(0);
|
||||
|
||||
term.buffer.active.viewportY = baseY - 5;
|
||||
for (const ev of [wheelLines(-12), wheelLines(12), wheelLines(-5), wheelLines(-5)]) {
|
||||
mount.fire('wheel', ev);
|
||||
expect(ev.preventDefault).not.toHaveBeenCalled();
|
||||
expect(ev.stopPropagation).not.toHaveBeenCalled();
|
||||
}
|
||||
expect(flushed(ws)).toEqual([]);
|
||||
|
||||
// Back on the live screen, only travel made there counts: two quarter-screen
|
||||
// wheels are one PageUp, with nothing carried over from the wheels xterm had
|
||||
// (the gate sits before the pending travel is touched).
|
||||
term.buffer.active.viewportY = baseY;
|
||||
const first = wheelLines(-6);
|
||||
mount.fire('wheel', first);
|
||||
expect(first.preventDefault).toHaveBeenCalled();
|
||||
expect(flushed(ws)).toEqual([]);
|
||||
mount.fire('wheel', wheelLines(-6));
|
||||
expect(flushed(ws)).toEqual([{ t: 'i', d: PAGE_UP }]);
|
||||
});
|
||||
|
||||
it('keeps paging when the PTY geometry report reflows the rows above the screen', async () => {
|
||||
serveCapture(lines(40), 40);
|
||||
const { tile, ws, term, mount } = await connectTile(makeApp({ 's-tile': { mode: 'opencode' } }));
|
||||
|
||||
Reference in New Issue
Block a user