| ... | @@ -129,42 +129,6 @@ export async function loadTerminalFontFamily( | ... | @@ -129,42 +129,6 @@ export async function loadTerminalFontFamily( |
| 129 | return (environment?.resolve ?? terminalFontFamily)(family); | 129 | return (environment?.resolve ?? terminalFontFamily)(family); |
| 130 | } | 130 | } |
| 131 | | 131 | |
| 132 | /** | | |
| 133 | * Grids narrower than a classic 80-column terminal wrap command output hard, | | |
| 134 | * so the rendered font size follows the canvas width: the preference is the | | |
| 135 | * ceiling, and the size slides down (to a legibility floor) until a full-width | | |
| 136 | * grid fits. A widening pane slides it back up toward the preference. | | |
| 137 | */ | | |
| 138 | const MIN_TERMINAL_FIT_COLUMNS = 80; | | |
| 139 | const MIN_TERMINAL_FIT_FONT_SIZE = 8; | | |
| 140 | | | |
| 141 | export function fittedTerminalFontSize( | | |
| 142 | cellWidthAt: (size: number) => number, | | |
| 143 | requested: number, | | |
| 144 | mountWidth: number, | | |
| 145 | ): number { | | |
| 146 | const available = mountWidth - CONTENT_PADDING * 2; | | |
| 147 | if (available <= 0) return requested; | | |
| 148 | const floor = Math.min(requested, MIN_TERMINAL_FIT_FONT_SIZE); | | |
| 149 | const fits = (cellWidth: number) => | | |
| 150 | cellWidth > 0 && Math.floor(available / cellWidth) >= MIN_TERMINAL_FIT_COLUMNS; | | |
| 151 | let cellWidth = cellWidthAt(requested); | | |
| 152 | if (cellWidth <= 0 || fits(cellWidth)) return requested; | | |
| 153 | // The advance scales linearly with size for monospace faces: jump close to | | |
| 154 | // the fitting size, then settle the remaining rounding one step at a time. | | |
| 155 | const targetCellWidth = available / MIN_TERMINAL_FIT_COLUMNS; | | |
| 156 | let size = Math.max( | | |
| 157 | floor, | | |
| 158 | Math.min(requested, Math.floor((requested * targetCellWidth) / cellWidth)), | | |
| 159 | ); | | |
| 160 | while (size > floor) { | | |
| 161 | cellWidth = cellWidthAt(size); | | |
| 162 | if (cellWidth <= 0 || fits(cellWidth)) break; | | |
| 163 | size -= 1; | | |
| 164 | } | | |
| 165 | return size; | | |
| 166 | } | | |
| 167 | | | |
| 168 | export function terminalFontSize(size?: number): number { | 132 | export function terminalFontSize(size?: number): number { |
| 169 | if (size === undefined || !Number.isFinite(size)) return DEFAULT_TERMINAL_FONT_SIZE; | 133 | if (size === undefined || !Number.isFinite(size)) return DEFAULT_TERMINAL_FONT_SIZE; |
| 170 | return Math.max(MIN_TERMINAL_FONT_SIZE, Math.min(MAX_TERMINAL_FONT_SIZE, Math.round(size))); | 134 | return Math.max(MIN_TERMINAL_FONT_SIZE, Math.min(MAX_TERMINAL_FONT_SIZE, Math.round(size))); |
| ... | @@ -519,7 +483,6 @@ export class GhosttyTerminalSurface { | ... | @@ -519,7 +483,6 @@ export class GhosttyTerminalSurface { |
| 519 | private fontFamily: string; | 483 | private fontFamily: string; |
| 520 | private requestedFontFamily: string | undefined; | 484 | private requestedFontFamily: string | undefined; |
| 521 | private fontSize: number; | 485 | private fontSize: number; |
| 522 | private requestedFontSize: number; | | |
| 523 | private fontEpoch = 0; | 486 | private fontEpoch = 0; |
| 524 | private pendingFontEpoch: number | null = null; | 487 | private pendingFontEpoch: number | null = null; |
| 525 | private readonly resizeObserver: ResizeObserver; | 488 | private readonly resizeObserver: ResizeObserver; |
| ... | @@ -601,7 +564,6 @@ export class GhosttyTerminalSurface { | ... | @@ -601,7 +564,6 @@ export class GhosttyTerminalSurface { |
| 601 | this.fontFamily = fontFamily; | 564 | this.fontFamily = fontFamily; |
| 602 | this.requestedFontFamily = options.font?.family; | 565 | this.requestedFontFamily = options.font?.family; |
| 603 | this.fontSize = terminalFontSize(options.font?.size); | 566 | this.fontSize = terminalFontSize(options.font?.size); |
| 604 | this.requestedFontSize = this.fontSize; | | |
| 605 | this.resizeObserver = new ResizeObserver(() => this.fit()); | 567 | this.resizeObserver = new ResizeObserver(() => this.fit()); |
| 606 | this.installEvents(); | 568 | this.installEvents(); |
| 607 | this.watchDevicePixelRatio(); | 569 | this.watchDevicePixelRatio(); |
| ... | @@ -719,7 +681,6 @@ export class GhosttyTerminalSurface { | ... | @@ -719,7 +681,6 @@ export class GhosttyTerminalSurface { |
| 719 | this.pendingFontEpoch = null; | 681 | this.pendingFontEpoch = null; |
| 720 | this.fontFamily = fontFamily; | 682 | this.fontFamily = fontFamily; |
| 721 | this.requestedFontFamily = font.family; | 683 | this.requestedFontFamily = font.family; |
| 722 | this.requestedFontSize = fontSize; | | |
| 723 | this.fontSize = fontSize; | 684 | this.fontSize = fontSize; |
| 724 | this.applyFontMetrics(); | 685 | this.applyFontMetrics(); |
| 725 | } | 686 | } |
| ... | @@ -775,22 +736,6 @@ export class GhosttyTerminalSurface { | ... | @@ -775,22 +736,6 @@ export class GhosttyTerminalSurface { |
| 775 | const width = this.mount.clientWidth; | 736 | const width = this.mount.clientWidth; |
| 776 | const height = this.mount.clientHeight; | 737 | const height = this.mount.clientHeight; |
| 777 | if (width <= 0 || height <= 0) return false; | 738 | if (width <= 0 || height <= 0) return false; |
| 778 | const fitted = fittedTerminalFontSize( | | |
| 779 | (size) => measureGhosttyCell(this.context, size, this.fontFamily).width, | | |
| 780 | this.requestedFontSize, | | |
| 781 | width, | | |
| 782 | ); | | |
| 783 | if (fitted !== this.fontSize) { | | |
| 784 | this.fontSize = fitted; | | |
| 785 | this.metrics = measureGhosttyCell(this.context, this.fontSize, this.fontFamily); | | |
| 786 | // The grid-change branch below resizes the core, but only when the | | |
| 787 | // column count moved; the cell geometry always did, so sync it here. | | |
| 788 | this.core.resize(this.cols, this.rows, this.metrics.width, this.metrics.height); | | |
| 789 | this.inputLeft = -1; | | |
| 790 | this.inputTop = -1; | | |
| 791 | this.forceFullRender = true; | | |
| 792 | this.scrollbarDirty = true; | | |
| 793 | } | | |
| 794 | const ratio = window.devicePixelRatio || 1; | 739 | const ratio = window.devicePixelRatio || 1; |
| 795 | const pixelWidth = Math.max(1, Math.round(width * ratio)); | 740 | const pixelWidth = Math.max(1, Math.round(width * ratio)); |
| 796 | const pixelHeight = Math.max(1, Math.round(height * ratio)); | 741 | const pixelHeight = Math.max(1, Math.round(height * ratio)); |