From 6b5fc260caf7bc310a760041161774ec5f536288 Mon Sep 17 00:00:00 2001 From: tisilent Date: Tue, 10 Oct 2023 22:53:01 +0800 Subject: [PATCH] Dom Renderer using SelectionRenderModel --- .../xterm-addon-canvas/src/BaseRenderLayer.ts | 2 +- addons/xterm-addon-webgl/src/WebglRenderer.ts | 2 +- src/browser/Terminal.ts | 2 +- src/browser/renderer/dom/DomRenderer.ts | 36 +++++++------------ .../renderer/shared/SelectionRenderModel.ts | 13 +++++-- src/browser/renderer/shared/Types.d.ts | 4 +-- 6 files changed, 27 insertions(+), 32 deletions(-) diff --git a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts b/addons/xterm-addon-canvas/src/BaseRenderLayer.ts index 8c199336..ba5dca66 100644 --- a/addons/xterm-addon-canvas/src/BaseRenderLayer.ts +++ b/addons/xterm-addon-canvas/src/BaseRenderLayer.ts @@ -91,7 +91,7 @@ export abstract class BaseRenderLayer extends Disposable implements IRenderLayer public handleGridChanged(startRow: number, endRow: number): void {} public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void { - this._selectionModel.update(this._terminal, start, end, columnSelectMode); + this._selectionModel.update((this._terminal as any)._core, start, end, columnSelectMode); } protected _setTransparency(alpha: boolean): void { diff --git a/addons/xterm-addon-webgl/src/WebglRenderer.ts b/addons/xterm-addon-webgl/src/WebglRenderer.ts index 8cc81b92..35fbfcb3 100644 --- a/addons/xterm-addon-webgl/src/WebglRenderer.ts +++ b/addons/xterm-addon-webgl/src/WebglRenderer.ts @@ -219,7 +219,7 @@ export class WebglRenderer extends Disposable implements IRenderer { for (const l of this._renderLayers) { l.handleSelectionChanged(this._terminal, start, end, columnSelectMode); } - this._model.selection.update(this._terminal, start, end, columnSelectMode); + this._model.selection.update(this._core, start, end, columnSelectMode); this._requestRedrawViewport(); } diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 18af3e4e..4198c84f 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -561,7 +561,7 @@ export class Terminal extends CoreTerminal implements ITerminal { } private _createRenderer(): IRenderer { - return this._instantiationService.createInstance(DomRenderer, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2); + return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2); } /** diff --git a/src/browser/renderer/dom/DomRenderer.ts b/src/browser/renderer/dom/DomRenderer.ts index 79f658b6..1549b130 100644 --- a/src/browser/renderer/dom/DomRenderer.ts +++ b/src/browser/renderer/dom/DomRenderer.ts @@ -7,9 +7,10 @@ import { DomRendererRowFactory, RowCss } from 'browser/renderer/dom/DomRendererR import { WidthCache } from 'browser/renderer/dom/WidthCache'; import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants'; import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils'; -import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types'; +import { createSelectionRenderModel } from 'browser/renderer/shared/SelectionRenderModel'; +import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ISelectionRenderModel } from 'browser/renderer/shared/Types'; import { ICharSizeService, ICoreBrowserService, IThemeService } from 'browser/services/Services'; -import { ILinkifier2, ILinkifierEvent, ReadonlyColorSet } from 'browser/Types'; +import { ILinkifier2, ILinkifierEvent, ITerminal, ReadonlyColorSet } from 'browser/Types'; import { color } from 'common/Color'; import { EventEmitter } from 'common/EventEmitter'; import { Disposable, toDisposable } from 'common/Lifecycle'; @@ -25,12 +26,6 @@ const SELECTION_CLASS = 'xterm-selection'; let nextTerminalId = 1; -interface ISelectionState { - columnSelectMode: boolean; - selectionStart: [number, number]| undefined; - selectionEnd: [number, number]| undefined; -} - /** * A fallback renderer for when canvas is slow. This is not meant to be * particularly fast or feature complete, more just stable and usable for when @@ -46,17 +41,14 @@ export class DomRenderer extends Disposable implements IRenderer { private _rowElements: HTMLElement[] = []; private _selectionContainer: HTMLElement; private _widthCache: WidthCache; - private _selectionState: ISelectionState = { - columnSelectMode: false, - selectionStart: undefined, - selectionEnd: undefined - }; + private _selectionRenderModel: ISelectionRenderModel = createSelectionRenderModel(); public dimensions: IRenderDimensions; public readonly onRequestRedraw = this.register(new EventEmitter()).event; constructor( + private readonly _terminal: ITerminal, private readonly _document: Document, private readonly _element: HTMLElement, private readonly _screenElement: HTMLElement, @@ -301,9 +293,7 @@ export class DomRenderer extends Disposable implements IRenderer { public handleResize(cols: number, rows: number): void { this._refreshRowElements(cols, rows); this._updateDimensions(); - if (this._selectionState.selectionStart && this._selectionState.selectionEnd) { - this.handleSelectionChanged(this._selectionState.selectionStart, this._selectionState.selectionEnd, this._selectionState.columnSelectMode); - } + this.handleSelectionChanged(this._selectionRenderModel.selectionStart, this._selectionRenderModel.selectionEnd, this._selectionRenderModel.columnSelectMode); } public handleCharSizeChanged(): void { @@ -323,10 +313,6 @@ export class DomRenderer extends Disposable implements IRenderer { } public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void { - this._selectionState.selectionStart = start; - this._selectionState.selectionEnd = end; - this._selectionState.columnSelectMode = columnSelectMode; - // Remove all selections this._selectionContainer.replaceChildren(); this._rowFactory.handleSelectionChanged(start, end, columnSelectMode); @@ -337,11 +323,13 @@ export class DomRenderer extends Disposable implements IRenderer { return; } + this._selectionRenderModel.update(this._terminal, start, end, columnSelectMode); + // Translate from buffer position to viewport position - const viewportStartRow = start[1] - this._bufferService.buffer.ydisp; - const viewportEndRow = end[1] - this._bufferService.buffer.ydisp; - const viewportCappedStartRow = Math.max(viewportStartRow, 0); - const viewportCappedEndRow = Math.min(viewportEndRow, this._bufferService.rows - 1); + const viewportStartRow = this._selectionRenderModel.viewportStartRow; + const viewportEndRow = this._selectionRenderModel.viewportEndRow; + const viewportCappedStartRow = this._selectionRenderModel.viewportCappedStartRow; + const viewportCappedEndRow = this._selectionRenderModel.viewportCappedEndRow; // No need to draw the selection if (viewportCappedStartRow >= this._bufferService.rows || viewportCappedEndRow < 0) { diff --git a/src/browser/renderer/shared/SelectionRenderModel.ts b/src/browser/renderer/shared/SelectionRenderModel.ts index db375778..3363ce9a 100644 --- a/src/browser/renderer/shared/SelectionRenderModel.ts +++ b/src/browser/renderer/shared/SelectionRenderModel.ts @@ -3,7 +3,9 @@ * @license MIT */ +import { ITerminal } from 'browser/Types'; import { ISelectionRenderModel } from 'browser/renderer/shared/Types'; +import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi'; import { Terminal } from 'xterm'; class SelectionRenderModel implements ISelectionRenderModel { @@ -17,6 +19,7 @@ class SelectionRenderModel implements ISelectionRenderModel { public endCol!: number; public selectionStart: [number, number] | undefined; public selectionEnd: [number, number] | undefined; + private _buffer: BufferNamespaceApi | undefined; constructor() { this.clear(); @@ -35,7 +38,11 @@ class SelectionRenderModel implements ISelectionRenderModel { this.selectionEnd = undefined; } - public update(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void { + public update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void { + if (!this._buffer) { + this._buffer = new BufferNamespaceApi(terminal); + } + this.selectionStart = start; this.selectionEnd = end; // Selection does not exist @@ -45,8 +52,8 @@ class SelectionRenderModel implements ISelectionRenderModel { } // Translate from buffer position to viewport position - const viewportStartRow = start[1] - terminal.buffer.active.viewportY; - const viewportEndRow = end[1] - terminal.buffer.active.viewportY; + const viewportStartRow = start[1] - this._buffer.active.viewportY; + const viewportEndRow = end[1] - this._buffer.active.viewportY; const viewportCappedStartRow = Math.max(viewportStartRow, 0); const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1); diff --git a/src/browser/renderer/shared/Types.d.ts b/src/browser/renderer/shared/Types.d.ts index a7e55e72..b42e7090 100644 --- a/src/browser/renderer/shared/Types.d.ts +++ b/src/browser/renderer/shared/Types.d.ts @@ -4,7 +4,7 @@ */ import { FontWeight, Terminal } from 'xterm'; -import { IColorSet } from 'browser/Types'; +import { IColorSet, ITerminal } from 'browser/Types'; import { IDisposable } from 'common/Types'; import { IEvent } from 'common/EventEmitter'; @@ -168,6 +168,6 @@ export interface ISelectionRenderModel { readonly selectionStart: [number, number] | undefined; readonly selectionEnd: [number, number] | undefined; clear(): void; - update(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void; + update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void; isCellSelected(terminal: Terminal, x: number, y: number): boolean; }