summaryrefslogtreecommitdiffstats
path: root/html/src/components/terminal/index.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'html/src/components/terminal/index.tsx')
-rw-r--r--html/src/components/terminal/index.tsx53
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));
}