* Seed prev/back frames with full-size BLANK screens (rows×cols of empty * cells, not 0×0). In alt-screen mode, next.screen.height is always * terminalRows; if prev.screen.height is 0 (emptyFrame's default), * log-update sees heightDelta > 0 ('growing') and calls renderFrameSlice, * whos
()
| 1131 | * matches the physical cursor after ENTER_ALT_SCREEN + CSI H (home). |
| 1132 | */ |
| 1133 | private resetFramesForAltScreen(): void { |
| 1134 | const rows = this.terminalRows; |
| 1135 | const cols = this.terminalColumns; |
| 1136 | const blank = (): Frame => ({ |
| 1137 | screen: createScreen(cols, rows, this.stylePool, this.charPool, this.hyperlinkPool), |
| 1138 | viewport: { |
| 1139 | width: cols, |
| 1140 | height: rows + 1 |
| 1141 | }, |
| 1142 | cursor: { |
| 1143 | x: 0, |
| 1144 | y: 0, |
| 1145 | visible: true |
| 1146 | } |
| 1147 | }); |
| 1148 | this.frontFrame = blank(); |
| 1149 | this.backFrame = blank(); |
| 1150 | this.logicalFrontFrame = this.frontFrame; |
| 1151 | this.logicalBackFrame = this.backFrame; |
| 1152 | this.log.reset(); |
| 1153 | this.altScreenPendingRepaintMode = 'none'; |
| 1154 | this.altScreenPendingPreviousFrame = undefined; |
| 1155 | // Defense-in-depth: alt-screen skips the cursor preamble anyway (CSI H |
| 1156 | // resets), but a stale displayCursor would be misleading if we later |
| 1157 | // exit to main-screen without an intervening render. |
| 1158 | this.displayCursor = null; |
| 1159 | // Fresh frontFrame is blank rows×cols — blitting from it would copy |
| 1160 | // blanks over content. Next alt-screen frame must full-render. |
| 1161 | this.prevFrameContaminated = true; |
| 1162 | } |
| 1163 | |
| 1164 | /** |
| 1165 | * Copy the current selection to the clipboard without clearing the |
no test coverage detected