fix(tui): preserve WezTerm Kitty images on full redraw
Reserve visible Kitty image rows before drawing placements in full redraws, while preserving the first-row path for taller-than-viewport images so #4415 stays fixed. Closes #5618.
This commit is contained in:
@@ -152,6 +152,95 @@ describe("TUI Kitty image cleanup", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("reserves Kitty image rows before drawing during full redraw fallbacks", async () => {
|
||||
setCapabilities({ images: "kitty", trueColor: true, hyperlinks: true });
|
||||
setCellDimensions({ widthPx: 10, heightPx: 10 });
|
||||
try {
|
||||
const terminal = new LoggingVirtualTerminal(40, 5);
|
||||
const tui = new TUI(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
|
||||
component.lines = ["l0", "l1", "l2", "l3", "l4"];
|
||||
tui.start();
|
||||
await terminal.waitForRender();
|
||||
const redrawsBeforeImage = tui.fullRedraws;
|
||||
terminal.clearWrites();
|
||||
|
||||
const image = new Image(
|
||||
"AAAA",
|
||||
"image/png",
|
||||
{ fallbackColor: (value) => value },
|
||||
{ maxWidthCells: 3 },
|
||||
{ widthPx: 30, heightPx: 30 },
|
||||
);
|
||||
const imageLines = image.render(40);
|
||||
const imageSequence = imageLines[0];
|
||||
component.lines = ["l0", "l1", "l2", "l3", "l4", ...imageLines, "after"];
|
||||
tui.requestRender();
|
||||
await terminal.waitForRender();
|
||||
|
||||
const writes = terminal.getWrites();
|
||||
assert.ok(tui.fullRedraws > redrawsBeforeImage, "scrolling image append should force a full redraw");
|
||||
assert.ok(
|
||||
writes.includes(`\r\n\r\n\x1b[2A${imageSequence}\x1b[2B`),
|
||||
"full redraw should reserve visible image rows before drawing the placement",
|
||||
);
|
||||
assert.ok(
|
||||
!writes.includes(`${imageSequence}\r\n\x1b[0m`),
|
||||
"full redraw must not write reserved padding rows after drawing the placement",
|
||||
);
|
||||
|
||||
tui.stop();
|
||||
} finally {
|
||||
resetCapabilitiesCache();
|
||||
setCellDimensions({ widthPx: 9, heightPx: 18 });
|
||||
}
|
||||
});
|
||||
|
||||
it("does not use cursor-up placement for Kitty images taller than the viewport", async () => {
|
||||
setCapabilities({ images: "kitty", trueColor: true, hyperlinks: true });
|
||||
setCellDimensions({ widthPx: 10, heightPx: 10 });
|
||||
try {
|
||||
const terminal = new LoggingVirtualTerminal(40, 5);
|
||||
const tui = new TUI(terminal);
|
||||
const component = new TestComponent();
|
||||
tui.addChild(component);
|
||||
|
||||
component.lines = ["before"];
|
||||
tui.start();
|
||||
await terminal.waitForRender();
|
||||
terminal.clearWrites();
|
||||
|
||||
const image = new Image(
|
||||
"AAAA",
|
||||
"image/png",
|
||||
{ fallbackColor: (value) => value },
|
||||
{ maxWidthCells: 6 },
|
||||
{ widthPx: 60, heightPx: 60 },
|
||||
);
|
||||
const imageLines = image.render(40);
|
||||
const imageSequence = imageLines[0];
|
||||
assert.ok(imageLines.length > terminal.rows, "test image should exceed the viewport height");
|
||||
|
||||
component.lines = ["before", ...imageLines, "after"];
|
||||
tui.requestRender(true);
|
||||
await terminal.waitForRender();
|
||||
|
||||
const writes = terminal.getWrites();
|
||||
assert.ok(writes.includes(imageSequence), "image placement should be drawn");
|
||||
assert.ok(
|
||||
!writes.includes(`\x1b[${imageLines.length - 1}A${imageSequence}`),
|
||||
"taller-than-viewport images must keep the #4461 first-row placement path",
|
||||
);
|
||||
|
||||
tui.stop();
|
||||
} finally {
|
||||
resetCapabilitiesCache();
|
||||
setCellDimensions({ widthPx: 9, heightPx: 18 });
|
||||
}
|
||||
});
|
||||
|
||||
it("deletes changed image ids before drawing moved placements", async () => {
|
||||
const terminal = new LoggingVirtualTerminal(40, 10);
|
||||
const tui = new TUI(terminal);
|
||||
|
||||
Reference in New Issue
Block a user