From cbddd2029ebdb8ed7db699d07b43191f056e0adf Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 27 Jul 2022 16:04:24 -0700 Subject: [PATCH] Get canvas renderer addon working --- addons/xterm-addon-canvas/src/CanvasAddon.ts | 46 ++++++++++--------- .../src/{Renderer.ts => CanvasRenderer.ts} | 2 +- demo/client.ts | 8 ++-- 3 files changed, 31 insertions(+), 25 deletions(-) rename addons/xterm-addon-canvas/src/{Renderer.ts => CanvasRenderer.ts} (99%) diff --git a/addons/xterm-addon-canvas/src/CanvasAddon.ts b/addons/xterm-addon-canvas/src/CanvasAddon.ts index 34fffb84..81594ef0 100644 --- a/addons/xterm-addon-canvas/src/CanvasAddon.ts +++ b/addons/xterm-addon-canvas/src/CanvasAddon.ts @@ -3,40 +3,44 @@ * @license MIT */ +import { IRenderService } from 'browser/services/Services'; +import { IColorSet } from 'browser/Types'; +import { CanvasRenderer } from './CanvasRenderer'; +import { IBufferService, IInstantiationService } from 'common/services/Services'; import { ITerminalAddon, Terminal } from 'xterm'; export class CanvasAddon implements ITerminalAddon { private _terminal?: Terminal; - // private _renderer?: WebglRenderer; + private _renderer?: CanvasRenderer; // private _onContextLoss = new EventEmitter(); // public get onContextLoss(): IEvent { return this._onContextLoss.event; } public activate(terminal: Terminal): void { - // if (!terminal.element) { - // throw new Error('Cannot activate WebglAddon before Terminal.open'); - // } - // if (isSafari) { - // throw new Error('Webgl is not currently supported on Safari'); - // } + if (!terminal.element) { + throw new Error('Cannot activate CanvasAddon before Terminal.open'); + } this._terminal = terminal; - // const renderService: IRenderService = (terminal as any)._core._renderService; - // const characterJoinerService: ICharacterJoinerService = (terminal as any)._core._characterJoinerService; - // const decorationService: IDecorationService = (terminal as any)._core._decorationService; - // const colors: IColorSet = (terminal as any)._core._colorManager.colors; - // this._renderer = new WebglRenderer(terminal, colors, characterJoinerService, decorationService, this._preserveDrawingBuffer); + const instantiationService: IInstantiationService = (terminal as any)._core._instantiationService; + const bufferService: IBufferService = (terminal as any)._core._renderService; + const renderService: IRenderService = (terminal as any)._core._renderService; + const colors: IColorSet = (terminal as any)._core._colorManager.colors; + const screenElement: HTMLElement = (terminal as any)._core.screenElement; + const linkifier = (terminal as any)._core.linkifier2; + this._renderer = instantiationService.createInstance(CanvasRenderer, colors, screenElement, linkifier); // this._renderer.onContextLoss(() => this._onContextLoss.fire()); - // renderService.setRenderer(this._renderer); + renderService.setRenderer(this._renderer); + renderService.onResize(bufferService.cols, bufferService.rows); } public dispose(): void { - // if (!this._terminal) { - // throw new Error('Cannot dispose WebglAddon because it is activated'); - // } - // const renderService: IRenderService = (this._terminal as any)._core._renderService; - // renderService.setRenderer((this._terminal as any)._core._createRenderer()); - // renderService.onResize(this._terminal.cols, this._terminal.rows); - // this._renderer?.dispose(); - // this._renderer = undefined; + if (!this._terminal) { + throw new Error('Cannot dispose CanvasAddon because it is activated'); + } + const renderService: IRenderService = (this._terminal as any)._core._renderService; + renderService.setRenderer((this._terminal as any)._core._createRenderer()); + renderService.onResize(this._terminal.cols, this._terminal.rows); + this._renderer?.dispose(); + this._renderer = undefined; } // public get textureAtlas(): HTMLCanvasElement | undefined { diff --git a/addons/xterm-addon-canvas/src/Renderer.ts b/addons/xterm-addon-canvas/src/CanvasRenderer.ts similarity index 99% rename from addons/xterm-addon-canvas/src/Renderer.ts rename to addons/xterm-addon-canvas/src/CanvasRenderer.ts index 629f69f4..88c81ea7 100644 --- a/addons/xterm-addon-canvas/src/Renderer.ts +++ b/addons/xterm-addon-canvas/src/CanvasRenderer.ts @@ -18,7 +18,7 @@ import { EventEmitter, IEvent } from 'common/EventEmitter'; let nextRendererId = 1; -export class Renderer extends Disposable implements IRenderer { +export class CanvasRenderer extends Disposable implements IRenderer { private _id = nextRendererId++; private _renderLayers: IRenderLayer[]; diff --git a/demo/client.ts b/demo/client.ts index e00279d7..3ee533d0 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -54,7 +54,7 @@ let socketURL; let socket; let pid; -type AddonType = 'attach' | 'fit' | 'search' | 'serialize' | 'unicode11' | 'web-links' | 'webgl' | 'ligatures'; +type AddonType = 'attach' | 'canvas' | 'fit' | 'search' | 'serialize' | 'unicode11' | 'web-links' | 'webgl' | 'ligatures'; interface IDemoAddon { name: T; @@ -84,6 +84,7 @@ interface IDemoAddon { const addons: { [T in AddonType]: IDemoAddon} = { attach: { name: 'attach', ctor: AttachAddon, canChange: false }, + canvas: { name: 'canvas', ctor: CanvasAddon, canChange: true }, fit: { name: 'fit', ctor: FitAddon, canChange: false }, search: { name: 'search', ctor: SearchAddon, canChange: true }, serialize: { name: 'serialize', ctor: SerializeAddon, canChange: true }, @@ -153,6 +154,7 @@ const disposeRecreateButtonHandler = () => { window.term = null; socket = null; addons.attach.instance = undefined; + addons.canvas.instance = undefined; addons.fit.instance = undefined; addons.search.instance = undefined; addons.serialize.instance = undefined; @@ -630,7 +632,7 @@ function writeCustomGlyphHandler() { } function loadTest() { - const isWebglEnabled = !!addons.webgl.instance; + const rendererName = addons.webgl.instance ? 'webgl' : !!addons.canvas.instance ? 'canvas' : 'dom'; const testData = []; let byteCount = 0; for (let i = 0; i < 50; i++) { @@ -656,7 +658,7 @@ function loadTest() { term.write('', () => { const time = Math.round(performance.now() - start); const mbs = ((byteCount / 1024) * (1 / (time / 1000))).toFixed(2); - term.write(`\n\r\nWrote ${byteCount}kB in ${time}ms (${mbs}MB/s) using the (${isWebglEnabled ? 'webgl' : 'canvas'} renderer)`); + term.write(`\n\r\nWrote ${byteCount}kB in ${time}ms (${mbs}MB/s) using the (${rendererName} renderer)`); // Send ^C to get a new prompt term._core._onData.fire('\x03'); });