Move WidthCache measure container to helper container

This commit is contained in:
Thomas Zilz
2023-09-15 10:51:31 +02:00
parent 0e66d608a1
commit aaadefa548
5 changed files with 23 additions and 17 deletions
+1 -1
View File
@@ -561,7 +561,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
} }
private _createRenderer(): IRenderer { private _createRenderer(): IRenderer {
return this._instantiationService.createInstance(DomRenderer, this.element!, this.screenElement!, this._viewportElement!, this.linkifier2); return this._instantiationService.createInstance(DomRenderer, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2);
} }
/** /**
+10 -8
View File
@@ -47,9 +47,11 @@ export class DomRenderer extends Disposable implements IRenderer {
public readonly onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>()).event; public readonly onRequestRedraw = this.register(new EventEmitter<IRequestRedrawEvent>()).event;
constructor( constructor(
private readonly _document: Document,
private readonly _element: HTMLElement, private readonly _element: HTMLElement,
private readonly _screenElement: HTMLElement, private readonly _screenElement: HTMLElement,
private readonly _viewportElement: HTMLElement, private readonly _viewportElement: HTMLElement,
private readonly _helperContainer: HTMLElement,
private readonly _linkifier2: ILinkifier2, private readonly _linkifier2: ILinkifier2,
@IInstantiationService instantiationService: IInstantiationService, @IInstantiationService instantiationService: IInstantiationService,
@ICharSizeService private readonly _charSizeService: ICharSizeService, @ICharSizeService private readonly _charSizeService: ICharSizeService,
@@ -59,12 +61,12 @@ export class DomRenderer extends Disposable implements IRenderer {
@IThemeService private readonly _themeService: IThemeService @IThemeService private readonly _themeService: IThemeService
) { ) {
super(); super();
this._rowContainer = document.createElement('div'); this._rowContainer = this._document.createElement('div');
this._rowContainer.classList.add(ROW_CONTAINER_CLASS); this._rowContainer.classList.add(ROW_CONTAINER_CLASS);
this._rowContainer.style.lineHeight = 'normal'; this._rowContainer.style.lineHeight = 'normal';
this._rowContainer.setAttribute('aria-hidden', 'true'); this._rowContainer.setAttribute('aria-hidden', 'true');
this._refreshRowElements(this._bufferService.cols, this._bufferService.rows); this._refreshRowElements(this._bufferService.cols, this._bufferService.rows);
this._selectionContainer = document.createElement('div'); this._selectionContainer = this._document.createElement('div');
this._selectionContainer.classList.add(SELECTION_CLASS); this._selectionContainer.classList.add(SELECTION_CLASS);
this._selectionContainer.setAttribute('aria-hidden', 'true'); this._selectionContainer.setAttribute('aria-hidden', 'true');
@@ -96,7 +98,7 @@ export class DomRenderer extends Disposable implements IRenderer {
this._dimensionsStyleElement.remove(); this._dimensionsStyleElement.remove();
})); }));
this._widthCache = new WidthCache(document); this._widthCache = new WidthCache(this._document, this._helperContainer);
this._widthCache.setFont( this._widthCache.setFont(
this._optionsService.rawOptions.fontFamily, this._optionsService.rawOptions.fontFamily,
this._optionsService.rawOptions.fontSize, this._optionsService.rawOptions.fontSize,
@@ -130,7 +132,7 @@ export class DomRenderer extends Disposable implements IRenderer {
} }
if (!this._dimensionsStyleElement) { if (!this._dimensionsStyleElement) {
this._dimensionsStyleElement = document.createElement('style'); this._dimensionsStyleElement = this._document.createElement('style');
this._screenElement.appendChild(this._dimensionsStyleElement); this._screenElement.appendChild(this._dimensionsStyleElement);
} }
@@ -150,7 +152,7 @@ export class DomRenderer extends Disposable implements IRenderer {
private _injectCss(colors: ReadonlyColorSet): void { private _injectCss(colors: ReadonlyColorSet): void {
if (!this._themeStyleElement) { if (!this._themeStyleElement) {
this._themeStyleElement = document.createElement('style'); this._themeStyleElement = this._document.createElement('style');
this._screenElement.appendChild(this._themeStyleElement); this._screenElement.appendChild(this._themeStyleElement);
} }
@@ -276,7 +278,7 @@ export class DomRenderer extends Disposable implements IRenderer {
private _refreshRowElements(cols: number, rows: number): void { private _refreshRowElements(cols: number, rows: number): void {
// Add missing elements // Add missing elements
for (let i = this._rowElements.length; i <= rows; i++) { for (let i = this._rowElements.length; i <= rows; i++) {
const row = document.createElement('div'); const row = this._document.createElement('div');
this._rowContainer.appendChild(row); this._rowContainer.appendChild(row);
this._rowElements.push(row); this._rowElements.push(row);
} }
@@ -330,7 +332,7 @@ export class DomRenderer extends Disposable implements IRenderer {
} }
// Create the selections // Create the selections
const documentFragment = document.createDocumentFragment(); const documentFragment = this._document.createDocumentFragment();
if (columnSelectMode) { if (columnSelectMode) {
const isXFlipped = start[0] > end[0]; const isXFlipped = start[0] > end[0];
@@ -362,7 +364,7 @@ export class DomRenderer extends Disposable implements IRenderer {
* @param colEnd The end columns. * @param colEnd The end columns.
*/ */
private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement { private _createSelectionElement(row: number, colStart: number, colEnd: number, rowCount: number = 1): HTMLElement {
const element = document.createElement('div'); const element = this._document.createElement('div');
element.style.height = `${rowCount * this.dimensions.css.cell.height}px`; element.style.height = `${rowCount * this.dimensions.css.cell.height}px`;
element.style.top = `${row * this.dimensions.css.cell.height}px`; element.style.top = `${row * this.dimensions.css.cell.height}px`;
element.style.left = `${colStart * this.dimensions.css.cell.width}px`; element.style.left = `${colStart * this.dimensions.css.cell.width}px`;
@@ -14,8 +14,8 @@ import { MockCoreService, MockDecorationService, MockOptionsService } from 'comm
import { MockCharacterJoinerService, MockCoreBrowserService, MockThemeService } from 'browser/TestUtils.test'; import { MockCharacterJoinerService, MockCoreBrowserService, MockThemeService } from 'browser/TestUtils.test';
import { TestWidthCache } from 'browser/renderer/dom/WidthCache.test'; import { TestWidthCache } from 'browser/renderer/dom/WidthCache.test';
const dom = new jsdom.JSDOM('');
const EMPTY_WIDTH = new TestWidthCache(new jsdom.JSDOM('').window.document); const EMPTY_WIDTH = new TestWidthCache(dom.window.document, dom.window.document.createElement('div'));
describe('DomRendererRowFactory', () => { describe('DomRendererRowFactory', () => {
+2 -1
View File
@@ -36,7 +36,8 @@ function castf32(v: number): number {
describe('WidthCache', () => { describe('WidthCache', () => {
let wc: TestWidthCache; let wc: TestWidthCache;
beforeEach(() => { beforeEach(() => {
wc = new TestWidthCache(new jsdom.JSDOM('').window.document); const dom = new jsdom.JSDOM('');
wc = new TestWidthCache(dom.window.document, dom.window.document.createElement('div'));
wc.setFont('monospace', 15, 'normal', 'bold'); wc.setFont('monospace', 15, 'normal', 'bold');
}); });
describe('cache invalidation', () => { describe('cache invalidation', () => {
+8 -5
View File
@@ -45,25 +45,28 @@ export class WidthCache implements IDisposable {
private _container: HTMLDivElement; private _container: HTMLDivElement;
private _measureElements: HTMLSpanElement[] = []; private _measureElements: HTMLSpanElement[] = [];
constructor(_document: Document) { constructor(_document: Document, _helperContainer: HTMLElement) {
this._container = _document.createElement('div'); this._container = _document.createElement('div');
this._container.style.position = 'absolute'; this._container.classList.add('xterm-width-cache-measure-container');
this._container.style.top = '-50000px'; this._container.setAttribute('aria-hidden', 'true');
this._container.style.width = '50000px';
// SP should stack in spans // SP should stack in spans
this._container.style.whiteSpace = 'pre'; this._container.style.whiteSpace = 'pre';
// avoid undercuts in non-monospace fonts from kerning // avoid undercuts in non-monospace fonts from kerning
this._container.style.fontKerning = 'none'; this._container.style.fontKerning = 'none';
const regular = _document.createElement('span'); const regular = _document.createElement('span');
regular.classList.add('xterm-char-measure-element');
const bold = _document.createElement('span'); const bold = _document.createElement('span');
bold.classList.add('xterm-char-measure-element');
bold.style.fontWeight = 'bold'; bold.style.fontWeight = 'bold';
const italic = _document.createElement('span'); const italic = _document.createElement('span');
italic.classList.add('xterm-char-measure-element');
italic.style.fontStyle = 'italic'; italic.style.fontStyle = 'italic';
const boldItalic = _document.createElement('span'); const boldItalic = _document.createElement('span');
boldItalic.classList.add('xterm-char-measure-element');
boldItalic.style.fontWeight = 'bold'; boldItalic.style.fontWeight = 'bold';
boldItalic.style.fontStyle = 'italic'; boldItalic.style.fontStyle = 'italic';
@@ -74,7 +77,7 @@ export class WidthCache implements IDisposable {
this._container.appendChild(italic); this._container.appendChild(italic);
this._container.appendChild(boldItalic); this._container.appendChild(boldItalic);
_document.body.appendChild(this._container); _helperContainer.appendChild(this._container);
this.clear(); this.clear();
} }