diff --git a/package.json b/package.json index 87320764..0e9985d3 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@table-nav/react": "^0.0.7", "@tanstack/match-sorter-utils": "^8.8.4", "@tanstack/react-table": "^8.10.3", + "@xterm/addon-webgl": "^0.17.0", "autobind-decorator": "^2.4.0", "base64-js": "^1.5.1", "classnames": "^2.3.1", diff --git a/src/plugins/terminal/term.ts b/src/plugins/terminal/term.ts index 8ff384bb..53aae0f1 100644 --- a/src/plugins/terminal/term.ts +++ b/src/plugins/terminal/term.ts @@ -11,6 +11,7 @@ import { boundMethod } from "autobind-decorator"; import { windowWidthToCols, windowHeightToRows } from "@/util/textmeasure"; import { boundInt } from "@/util/util"; import { GlobalModel } from "@/models"; +import { WebglAddon } from "@xterm/addon-webgl"; type DataUpdate = { data: Uint8Array; @@ -20,6 +21,20 @@ type DataUpdate = { const MinTermCols = 10; const MaxTermCols = 1024; +// 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 TermWrapOpts = { termContext: TermContextUnion; usedRows?: number; @@ -142,6 +157,17 @@ class TermWrap { } }) ); + if (WebGLSupported && GlobalModel.clientData.get().clientopts?.webgl) { + const webglAddon = new WebglAddon(); + webglAddon.onContextLoss(() => { + webglAddon.dispose(); + }); + this.terminal.loadAddon(webglAddon); + if (!loggedWebGL) { + console.log("loaded webgl!"); + loggedWebGL = true; + } + } this.terminal._core._inputHandler._parser.setErrorHandler((state) => { this.numParseErrors++; return state; diff --git a/src/types/custom.d.ts b/src/types/custom.d.ts index e013ea7a..9d1ebb56 100644 --- a/src/types/custom.d.ts +++ b/src/types/custom.d.ts @@ -588,6 +588,7 @@ declare global { }; globalshortcut: string; globalshortcutenabled: boolean; + webgl: boolean; }; type ReleaseInfoType = { diff --git a/wavesrv/pkg/cmdrunner/cmdrunner.go b/wavesrv/pkg/cmdrunner/cmdrunner.go index 7e2a33f8..120d8183 100644 --- a/wavesrv/pkg/cmdrunner/cmdrunner.go +++ b/wavesrv/pkg/cmdrunner/cmdrunner.go @@ -5849,8 +5849,20 @@ func ClientSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sc return nil, fmt.Errorf("error updating client openai base url: %v", err) } } + if webglStr, found := pk.Kwargs["webgl"]; found { + webglVal := resolveBool(webglStr, false) + if webglVal { + varsUpdated = append(varsUpdated, "webgl") + } + clientOpts := clientData.ClientOpts + clientOpts.WebGL = webglVal + err = sstore.SetClientOpts(ctx, clientOpts) + if err != nil { + return nil, fmt.Errorf("error updating client webgl: %v", err) + } + } if len(varsUpdated) == 0 { - return nil, fmt.Errorf("/client:set requires a value to set: %s", formatStrs([]string{"termfontsize", "termfontfamily", "openaiapitoken", "openaimodel", "openaibaseurl", "openaimaxtokens", "openaimaxchoices"}, "or", false)) + return nil, fmt.Errorf("/client:set requires a value to set: %s", formatStrs([]string{"termfontsize", "termfontfamily", "openaiapitoken", "openaimodel", "openaibaseurl", "openaimaxtokens", "openaimaxchoices", "webgl"}, "or", false)) } clientData, err = sstore.EnsureClientData(ctx) if err != nil { diff --git a/wavesrv/pkg/sstore/sstore.go b/wavesrv/pkg/sstore/sstore.go index ab7d8bc3..27771b78 100644 --- a/wavesrv/pkg/sstore/sstore.go +++ b/wavesrv/pkg/sstore/sstore.go @@ -246,6 +246,7 @@ type ClientOptsType struct { RightSidebar *SidebarValueType `json:"rightsidebar,omitempty"` GlobalShortcut string `json:"globalshortcut,omitempty"` GlobalShortcutEnabled bool `json:"globalshortcutenabled,omitempty"` + WebGL bool `json:"webgl,omitempty"` } type FeOptsType struct { diff --git a/yarn.lock b/yarn.lock index 93a6d5ba..14a52fc7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2707,6 +2707,11 @@ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw== +"@xterm/addon-webgl@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@xterm/addon-webgl/-/addon-webgl-0.17.0.tgz#1da534456b7971ebb2f08c381d4732d1f104d7d8" + integrity sha512-KUH//EZCz7j1+IekW8sZzmcj/y9gOLf/HMcsWXjg0Xr5cT1lIBIIbbBlbf5kZ+XnA/8c1IuBm1vx+blzlfPk0g== + "@xtuc/ieee754@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"