mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
Add WebGL acceleration and link handling to terminal (#205)
This PR adds back WebGL acceleration (enabled by default) for XTerm. It also adds back link handling and adds a new option (disabled by default) to open all links internally as a new web block. --------- Co-authored-by: sawka <mike.sawka@gmail.com>
This commit is contained in:
parent
3c8bac6bf9
commit
7b87b7d7b9
@ -435,6 +435,20 @@ function isDev() {
|
||||
return cachedIsDev;
|
||||
}
|
||||
|
||||
async function openLink(uri: string) {
|
||||
if (globalStore.get(atoms.settingsConfigAtom)?.web?.openlinksinternally) {
|
||||
const blockDef: BlockDef = {
|
||||
meta: {
|
||||
view: "web",
|
||||
url: uri,
|
||||
},
|
||||
};
|
||||
await createBlock(blockDef);
|
||||
} else {
|
||||
getApi().openExternal(uri);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PLATFORM,
|
||||
WOS,
|
||||
@ -451,6 +465,7 @@ export {
|
||||
initGlobal,
|
||||
initWS,
|
||||
isDev,
|
||||
openLink,
|
||||
sendWSCommand,
|
||||
setBlockFocus,
|
||||
setPlatform,
|
||||
|
@ -425,7 +425,7 @@ function TableBody({
|
||||
{
|
||||
label: "Open Preview in New Block",
|
||||
click: async () => {
|
||||
const blockDef = {
|
||||
const blockDef: BlockDef = {
|
||||
meta: {
|
||||
view: "preview",
|
||||
file: path,
|
||||
|
@ -9,14 +9,13 @@ import * as keyutil from "@/util/keyutil";
|
||||
import clsx from "clsx";
|
||||
import { produce } from "immer";
|
||||
import * as jotai from "jotai";
|
||||
import "public/xterm.css";
|
||||
import * as React from "react";
|
||||
import { TermStickers } from "./termsticker";
|
||||
import { TermThemeUpdater } from "./termtheme";
|
||||
import { computeTheme } from "./termutil";
|
||||
import { TermWrap } from "./termwrap";
|
||||
|
||||
import "public/xterm.css";
|
||||
|
||||
const keyMap = {
|
||||
Enter: "\r",
|
||||
Backspace: "\x7f",
|
||||
@ -248,6 +247,7 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
|
||||
},
|
||||
{
|
||||
keydownHandler: handleTerminalKeydown,
|
||||
useWebGl: !termSettings?.disablewebgl,
|
||||
}
|
||||
);
|
||||
(window as any).term = termWrap;
|
||||
|
@ -2,15 +2,36 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { WshServer } from "@/app/store/wshserver";
|
||||
import { PLATFORM, fetchWaveFile, getFileSubject, sendWSCommand } from "@/store/global";
|
||||
import { PLATFORM, fetchWaveFile, getFileSubject, openLink, sendWSCommand } from "@/store/global";
|
||||
import * as services from "@/store/services";
|
||||
import { base64ToArray } from "@/util/util";
|
||||
import { base64ToArray, fireAndForget } from "@/util/util";
|
||||
import { SerializeAddon } from "@xterm/addon-serialize";
|
||||
import { WebLinksAddon } from "@xterm/addon-web-links";
|
||||
import { WebglAddon } from "@xterm/addon-webgl";
|
||||
import * as TermTypes from "@xterm/xterm";
|
||||
import { Terminal } from "@xterm/xterm";
|
||||
import { debounce } from "throttle-debounce";
|
||||
import { FitAddon } from "./fitaddon";
|
||||
|
||||
// detect webgl support
|
||||
function detectWebGLSupport(): boolean {
|
||||
try {
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("webgl");
|
||||
return !!ctx;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const WebGLSupported = detectWebGLSupport();
|
||||
let loggedWebGL = false;
|
||||
|
||||
type TermWrapOptions = {
|
||||
keydownHandler?: (e: KeyboardEvent) => void;
|
||||
useWebGl?: boolean;
|
||||
};
|
||||
|
||||
export class TermWrap {
|
||||
blockId: string;
|
||||
ptyOffset: number;
|
||||
@ -30,7 +51,7 @@ export class TermWrap {
|
||||
blockId: string,
|
||||
connectElem: HTMLDivElement,
|
||||
options: TermTypes.ITerminalOptions & TermTypes.ITerminalInitOnlyOptions,
|
||||
waveOptions: { keydownHandler?: (e: KeyboardEvent) => void }
|
||||
waveOptions: TermWrapOptions
|
||||
) {
|
||||
this.blockId = blockId;
|
||||
this.ptyOffset = 0;
|
||||
@ -41,6 +62,35 @@ export class TermWrap {
|
||||
this.serializeAddon = new SerializeAddon();
|
||||
this.terminal.loadAddon(this.fitAddon);
|
||||
this.terminal.loadAddon(this.serializeAddon);
|
||||
|
||||
this.terminal.loadAddon(
|
||||
new WebLinksAddon((e, uri) => {
|
||||
e.preventDefault();
|
||||
switch (PLATFORM) {
|
||||
case "darwin":
|
||||
if (e.metaKey) {
|
||||
fireAndForget(() => openLink(uri));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (e.ctrlKey) {
|
||||
fireAndForget(() => openLink(uri));
|
||||
}
|
||||
break;
|
||||
}
|
||||
})
|
||||
);
|
||||
if (WebGLSupported && waveOptions.useWebGl) {
|
||||
const webglAddon = new WebglAddon();
|
||||
webglAddon.onContextLoss(() => {
|
||||
webglAddon.dispose();
|
||||
});
|
||||
this.terminal.loadAddon(webglAddon);
|
||||
if (!loggedWebGL) {
|
||||
console.log("loaded webgl!");
|
||||
loggedWebGL = true;
|
||||
}
|
||||
}
|
||||
this.connectElem = connectElem;
|
||||
this.mainFileSubject = null;
|
||||
this.loaded = false;
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2024, Command Line Inc.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { getApi } from "@/app/store/global";
|
||||
import { openLink } from "@/app/store/global";
|
||||
import { WOS, globalStore } from "@/store/global";
|
||||
import * as services from "@/store/services";
|
||||
import clsx from "clsx";
|
||||
@ -336,7 +336,7 @@ const WebView = memo(({ parentRef, model }: WebViewProps) => {
|
||||
webview.addEventListener("new-window", (e: any) => {
|
||||
e.preventDefault();
|
||||
const newUrl = e.detail.url;
|
||||
getApi().openExternal(newUrl);
|
||||
openLink(newUrl);
|
||||
});
|
||||
|
||||
// Suppress errors
|
||||
|
7
frontend/types/gotypes.d.ts
vendored
7
frontend/types/gotypes.d.ts
vendored
@ -323,6 +323,7 @@ declare global {
|
||||
autoupdate: AutoUpdateOpts;
|
||||
termthemes: {[key: string]: TermThemeType};
|
||||
window: WindowSettingsType;
|
||||
web: WebConfigType;
|
||||
defaultmeta?: MetaType;
|
||||
presets?: {[key: string]: MetaType};
|
||||
};
|
||||
@ -398,6 +399,7 @@ declare global {
|
||||
type TerminalConfigType = {
|
||||
fontsize?: number;
|
||||
fontfamily?: string;
|
||||
disablewebgl: boolean;
|
||||
};
|
||||
|
||||
// wstore.UIContext
|
||||
@ -545,6 +547,11 @@ declare global {
|
||||
args: any[];
|
||||
};
|
||||
|
||||
// wconfig.WebConfigType
|
||||
type WebConfigType = {
|
||||
openlinksinternally: boolean;
|
||||
};
|
||||
|
||||
// service.WebReturnType
|
||||
type WebReturnType = {
|
||||
success?: boolean;
|
||||
|
@ -83,6 +83,8 @@
|
||||
"@types/color": "^3.0.6",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/addon-serialize": "^0.13.0",
|
||||
"@xterm/addon-web-links": "^0.11.0",
|
||||
"@xterm/addon-webgl": "^0.18.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"clsx": "^2.1.1",
|
||||
|
@ -25,8 +25,13 @@ type WidgetsConfigType struct {
|
||||
}
|
||||
|
||||
type TerminalConfigType struct {
|
||||
FontSize int `json:"fontsize,omitempty"`
|
||||
FontFamily string `json:"fontfamily,omitempty"`
|
||||
FontSize int `json:"fontsize,omitempty"`
|
||||
FontFamily string `json:"fontfamily,omitempty"`
|
||||
DisableWebGl bool `json:"disablewebgl"`
|
||||
}
|
||||
|
||||
type WebConfigType struct {
|
||||
OpenLinksInternally bool `json:"openlinksinternally"`
|
||||
}
|
||||
|
||||
type AiConfigType struct {
|
||||
@ -99,6 +104,7 @@ type SettingsConfigType struct {
|
||||
AutoUpdate *AutoUpdateOpts `json:"autoupdate"`
|
||||
TermThemes TermThemesConfigType `json:"termthemes"`
|
||||
WindowSettings WindowSettingsType `json:"window"`
|
||||
Web WebConfigType `json:"web"`
|
||||
|
||||
DefaultMeta *waveobj.MetaMapType `json:"defaultmeta,omitempty"`
|
||||
Presets map[string]*waveobj.MetaMapType `json:"presets,omitempty"`
|
||||
|
20
yarn.lock
20
yarn.lock
@ -4570,6 +4570,24 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@xterm/addon-web-links@npm:^0.11.0":
|
||||
version: 0.11.0
|
||||
resolution: "@xterm/addon-web-links@npm:0.11.0"
|
||||
peerDependencies:
|
||||
"@xterm/xterm": ^5.0.0
|
||||
checksum: 10c0/9426bed80afa954b0ea97771d041eb44e77a64e560ce8b8ef507a5d3a763979af18ae9f74ed54007bb7e235d0daf035be2a33f90d8edfecb431caf8ba0b0664e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@xterm/addon-webgl@npm:^0.18.0":
|
||||
version: 0.18.0
|
||||
resolution: "@xterm/addon-webgl@npm:0.18.0"
|
||||
peerDependencies:
|
||||
"@xterm/xterm": ^5.0.0
|
||||
checksum: 10c0/682a3f5f128ee09a0cf1b41cbb7b2f925a5e43056e12ba0c523b93a1f5f188045caef9e31f32db933b8a7a1b12d8f9babaddfa11e6f11df0c7b265009103476c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@xterm/xterm@npm:^5.5.0":
|
||||
version: 5.5.0
|
||||
resolution: "@xterm/xterm@npm:5.5.0"
|
||||
@ -12352,6 +12370,8 @@ __metadata:
|
||||
"@vitest/coverage-istanbul": "npm:^2.0.5"
|
||||
"@xterm/addon-fit": "npm:^0.10.0"
|
||||
"@xterm/addon-serialize": "npm:^0.13.0"
|
||||
"@xterm/addon-web-links": "npm:^0.11.0"
|
||||
"@xterm/addon-webgl": "npm:^0.18.0"
|
||||
"@xterm/xterm": "npm:^5.5.0"
|
||||
base64-js: "npm:^1.5.1"
|
||||
clsx: "npm:^2.1.1"
|
||||
|
Loading…
Reference in New Issue
Block a user