mirror of
https://github.com/tsl0922/ttyd.git
synced 2026-01-07 03:14:22 +01:00
html: use webgl as the default renderer
This commit is contained in:
@@ -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 <Xterm id="terminal-container" wsUrl={wsUrl} tokenUrl={tokenUrl} options={termOptions} />;
|
||||
return (
|
||||
<Xterm
|
||||
id="terminal-container"
|
||||
wsUrl={wsUrl}
|
||||
tokenUrl={tokenUrl}
|
||||
clientOptions={clientOptions}
|
||||
termOptions={termOptions}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Props> {
|
||||
@@ -44,9 +52,11 @@ export class Xterm extends Component<Props> {
|
||||
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<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 = () => {
|
||||
@@ -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');
|
||||
@@ -208,6 +266,8 @@ export class Xterm extends Component<Props> {
|
||||
fitAddon.fit();
|
||||
}
|
||||
|
||||
this.applyOptions(this.props.clientOptions);
|
||||
|
||||
terminal.focus();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -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}`);
|
||||
|
||||
Reference in New Issue
Block a user