From: Shuanglei Tao Date: Sat, 19 Dec 2020 04:09:47 +0000 (+0800) Subject: html: use webgl as the default renderer X-Git-Url: http://git.prime8.dev/?a=commitdiff_plain;h=c62de531042678b09a4096d7d8e4d6e057ee1e62;p=ttyd.git html: use webgl as the default renderer --- diff --git a/html/src/components/app.tsx b/html/src/components/app.tsx index dfe4b1e..a899b7f 100644 --- a/html/src/components/app.tsx +++ b/html/src/components/app.tsx @@ -1,7 +1,7 @@ import { h, Component } from 'preact'; import { ITerminalOptions, ITheme } from 'xterm'; -import { Xterm } from './terminal'; +import { ClientOptions, Xterm } from './terminal'; if ((module as any).hot) { // tslint:disable-next-line:no-var-requires @@ -12,6 +12,12 @@ const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const path = window.location.pathname.replace(/[\/]+$/, ''); const wsUrl = [protocol, '//', window.location.host, path, '/ws', window.location.search].join(''); const tokenUrl = [window.location.protocol, '//', window.location.host, path, '/token'].join(''); +const clientOptions = { + rendererType: 'webgl', + disableLeaveAlert: false, + disableResizeOverlay: false, + titleFixed: null, +} as ClientOptions; const termOptions = { fontSize: 13, fontFamily: 'Menlo For Powerline,Consolas,Liberation Mono,Menlo,Courier,monospace', @@ -40,6 +46,14 @@ const termOptions = { export class App extends Component { render() { - return ; + return ( + + ); } } diff --git a/html/src/components/terminal/index.tsx b/html/src/components/terminal/index.tsx index 870261f..8d5ec14 100644 --- a/html/src/components/terminal/index.tsx +++ b/html/src/components/terminal/index.tsx @@ -32,11 +32,19 @@ const enum Command { RESIZE_TERMINAL = '1', } +export interface ClientOptions { + rendererType: 'dom' | 'canvas' | 'webgl'; + disableLeaveAlert: boolean; + disableResizeOverlay: boolean; + titleFixed: string; +} + interface Props { id: string; wsUrl: string; tokenUrl: string; - options: ITerminalOptions; + clientOptions: ClientOptions; + termOptions: ITerminalOptions; } export class Xterm extends Component { @@ -44,9 +52,11 @@ export class Xterm extends Component { private textDecoder: TextDecoder; private container: HTMLElement; private terminal: Terminal; + private fitAddon: FitAddon; private overlayAddon: OverlayAddon; private zmodemAddon: ZmodemAddon; + private socket: WebSocket; private token: string; private title: string; @@ -149,7 +159,7 @@ export class Xterm extends Component { @bind private openTerminal() { - this.terminal = new Terminal(this.props.options); + this.terminal = new Terminal(this.props.termOptions); const { terminal, container, fitAddon, overlayAddon } = this; window.term = terminal as TtydTerminal; window.term.fit = () => { @@ -190,6 +200,54 @@ export class Xterm extends Component { socket.onerror = this.onSocketError; } + @bind + private applyOptions(options: any) { + const { terminal, fitAddon } = this; + const isWebGL2Available = () => { + try { + const canvas = document.createElement('canvas'); + return !!(window.WebGL2RenderingContext && canvas.getContext('webgl2')); + } catch (e) { + return false; + } + }; + + Object.keys(options).forEach(key => { + const value = options[key]; + switch (key) { + case 'rendererType': + if (value === 'webgl' && isWebGL2Available()) { + terminal.loadAddon(new WebglAddon()); + console.log(`[ttyd] WebGL renderer enabled`); + } + break; + case 'disableLeaveAlert': + if (value) { + window.removeEventListener('beforeunload', this.onWindowUnload); + console.log('[ttyd] Leave site alert disabled'); + } + break; + case 'disableResizeOverlay': + if (value) { + console.log(`[ttyd] Resize overlay disabled`); + this.resizeOverlay = false; + } + break; + case 'titleFixed': + if (!value || value === '') return; + console.log(`[ttyd] setting fixed title: ${value}`); + this.titleFixed = value; + document.title = value; + break; + default: + console.log(`[ttyd] option: ${key}=${value}`); + terminal.setOption(key, value); + if (key.indexOf('font') === 0) fitAddon.fit(); + break; + } + }); + } + @bind private onSocketOpen() { console.log('[ttyd] websocket connection opened'); @@ -208,6 +266,8 @@ export class Xterm extends Component { fitAddon.fit(); } + this.applyOptions(this.props.clientOptions); + terminal.focus(); } @@ -235,7 +295,7 @@ export class Xterm extends Component { @bind private onSocketData(event: MessageEvent) { - const { terminal, textDecoder, zmodemAddon, fitAddon } = this; + const { textDecoder, zmodemAddon } = this; const rawData = event.data as ArrayBuffer; const cmd = String.fromCharCode(new Uint8Array(rawData)[0]); const data = rawData.slice(1); @@ -249,44 +309,7 @@ export class Xterm extends Component { document.title = this.title; break; case Command.SET_PREFERENCES: - const preferences = JSON.parse(textDecoder.decode(data)); - Object.keys(preferences).forEach(key => { - const value = preferences[key]; - switch (key) { - case 'rendererType': - if (preferences[key] === 'webgl') { - terminal.loadAddon(new WebglAddon()); - console.log(`[ttyd] WebGL renderer enabled`); - } - break; - case 'disableLeaveAlert': - if (preferences[key]) { - window.removeEventListener('beforeunload', this.onWindowUnload); - console.log('[ttyd] Leave site alert disabled'); - } - break; - case 'disableResizeOverlay': - if (preferences[key]) { - console.log(`[ttyd] disabled resize overlay`); - this.resizeOverlay = false; - } - break; - case 'fontSize': - console.log(`[ttyd] setting font size to ${value}`); - terminal.setOption(key, value); - fitAddon.fit(); - break; - case 'titleFixed': - console.log(`[ttyd] setting fixed title: ${value}`); - this.titleFixed = value; - document.title = value; - break; - default: - console.log(`[ttyd] option: ${key}=${value}`); - terminal.setOption(key, value); - break; - } - }); + this.applyOptions(JSON.parse(textDecoder.decode(data))); break; default: console.warn(`[ttyd] unknown command: ${cmd}`);