Skip to content

Commit

Permalink
html: use webgl as the default renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
tsl0922 committed Dec 19, 2020
1 parent a109730 commit c62de53
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 43 deletions.
18 changes: 16 additions & 2 deletions html/src/components/app.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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',
Expand Down Expand Up @@ -40,6 +46,14 @@ const termOptions = {

export class App extends Component {
render() {
return <Xterm id="terminal-container" wsUrl={wsUrl} tokenUrl={tokenUrl} options={termOptions} />;
return (
<Xterm
id="terminal-container"
wsUrl={wsUrl}
tokenUrl={tokenUrl}
clientOptions={clientOptions}
termOptions={termOptions}
/>
);
}
}
105 changes: 64 additions & 41 deletions html/src/components/terminal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,31 @@ 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<Props> {
private textEncoder: TextEncoder;
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;
Expand Down Expand Up @@ -149,7 +159,7 @@ export class Xterm extends Component<Props> {

@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 = () => {
Expand Down Expand Up @@ -190,6 +200,54 @@ export class Xterm extends Component<Props> {
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');
Expand All @@ -208,6 +266,8 @@ export class Xterm extends Component<Props> {
fitAddon.fit();
}

this.applyOptions(this.props.clientOptions);

terminal.focus();
}

Expand Down Expand Up @@ -235,7 +295,7 @@ export class Xterm extends Component<Props> {

@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);
Expand All @@ -249,44 +309,7 @@ export class Xterm extends Component<Props> {
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}`);
Expand Down

0 comments on commit c62de53

Please sign in to comment.