diff options
Diffstat (limited to 'html/src/components/terminal')
-rw-r--r-- | html/src/components/terminal/index.tsx | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/html/src/components/terminal/index.tsx b/html/src/components/terminal/index.tsx index 7368915..1efba2e 100644 --- a/html/src/components/terminal/index.tsx +++ b/html/src/components/terminal/index.tsx @@ -1,6 +1,6 @@ import { bind } from 'decko'; import { Component, h } from 'preact'; -import { ITerminalOptions, Terminal } from 'xterm'; +import { ITerminalOptions, RendererType, Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; import { WebglAddon } from 'xterm-addon-webgl'; import { WebLinksAddon } from 'xterm-addon-web-links'; @@ -192,6 +192,7 @@ export class Xterm extends Component<Props> { }); } terminal.open(container); + fitAddon.fit(); } @bind @@ -207,35 +208,38 @@ export class Xterm extends Component<Props> { } @bind - private setRendererType(value: string) { - const isWebGL2Available = () => { + private setRendererType(value: 'webgl' | RendererType) { + const { terminal } = this; + + const disposeWebglRenderer = () => { try { - const canvas = document.createElement('canvas'); - return !!(window.WebGL2RenderingContext && canvas.getContext('webgl2')); - } catch (e) { - return false; + this.webglAddon?.dispose(); + } catch { + // ignore } + this.webglAddon = undefined; }; - const { terminal } = this; switch (value) { case 'webgl': if (this.webglAddon) return; - if (isWebGL2Available()) { - this.webglAddon = new WebglAddon(); - terminal.loadAddon(this.webglAddon); - console.log(`[ttyd] WebGL renderer enabled`); + try { + if (window.WebGL2RenderingContext && document.createElement('canvas').getContext('webgl2')) { + this.webglAddon = new WebglAddon(); + this.webglAddon.onContextLoss(() => { + disposeWebglRenderer(); + }); + terminal.loadAddon(this.webglAddon); + console.log(`[ttyd] WebGL renderer enabled`); + } + } catch (e) { + console.warn(`[ttyd] webgl2 init error`, e); } break; default: - try { - this.webglAddon?.dispose(); - } catch { - // ignore - } - this.webglAddon = undefined; + disposeWebglRenderer(); console.log(`[ttyd] option: rendererType=${value}`); - terminal.setOption('rendererType', value); + terminal.options.rendererType = value; break; } } @@ -275,8 +279,12 @@ export class Xterm extends Component<Props> { document.title = value; break; default: - console.log(`[ttyd] option: ${key}=${value}`); - terminal.setOption(key, value); + console.log(`[ttyd] option: ${key}=${JSON.stringify(value)}`); + if (terminal.options[key] instanceof Object) { + terminal.options[key] = Object.assign({}, terminal.options[key], value); + } else { + terminal.options[key] = value; + } if (key.indexOf('font') === 0) fitAddon.fit(); break; } @@ -305,7 +313,6 @@ export class Xterm extends Component<Props> { overlayAddon.showOverlay('Reconnected', 300); } else { this.opened = true; - fitAddon.fit(); } this.doReconnect = this.reconnect; @@ -372,7 +379,7 @@ export class Xterm extends Component<Props> { @bind private onTerminalResize(size: { cols: number; rows: number }) { const { overlayAddon, socket, textEncoder, resizeOverlay } = this; - if (socket.readyState === WebSocket.OPEN) { + if (socket && socket.readyState === WebSocket.OPEN) { const msg = JSON.stringify({ columns: size.cols, rows: size.rows }); socket.send(textEncoder.encode(Command.RESIZE_TERMINAL + msg)); } |