Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
369ca9b525 | ||
|
|
a5422d1b11 | ||
|
|
c2890d8a4d | ||
|
|
7a7abddc45 | ||
|
|
8c71bfd65f | ||
|
|
3c2b911439 | ||
|
|
5ee8760418 |
@@ -5,7 +5,7 @@
|
||||
|
||||
import { IColorContrastCache } from 'browser/Types';
|
||||
import { DIM_OPACITY, TEXT_BASELINE } from './Constants';
|
||||
import { tryDrawCustomGlyph } from './customGlyphs/CustomGlyphRasterizer';
|
||||
import { loadCustomGlyphDefinitions, tryDrawCustomGlyph } from './customGlyphs/CustomGlyphRasterizer';
|
||||
import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from './Types';
|
||||
import { NULL_COLOR, channels, color, rgba } from 'common/Color';
|
||||
@@ -100,6 +100,10 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
alpha: this._config.allowTransparency,
|
||||
willReadFrequently: true
|
||||
}));
|
||||
// Start loading custom glyph definitions asynchronously if custom glyphs are enabled
|
||||
if (this._config.customGlyphs !== false) {
|
||||
loadCustomGlyphDefinitions();
|
||||
}
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
|
||||
@@ -4,8 +4,38 @@
|
||||
*/
|
||||
|
||||
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||
import { customGlyphDefinitions } from './CustomGlyphDefinitions';
|
||||
import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, type CustomGlyphDefinitionPart, type CustomGlyphPathDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from './Types';
|
||||
import { CustomGlyphDefinitionType, CustomGlyphScaleType, CustomGlyphVectorType, type CustomGlyphCharacterDefinition, type CustomGlyphDefinitionPart, type CustomGlyphPathDrawFunctionDefinition, type CustomGlyphPatternDefinition, type ICustomGlyphSolidOctantBlockVector, type ICustomGlyphVectorShape } from './Types';
|
||||
|
||||
/**
|
||||
* Cached custom glyph definitions. This is loaded dynamically to support code splitting.
|
||||
*/
|
||||
let customGlyphDefinitions: { [index: string]: CustomGlyphCharacterDefinition | undefined } | undefined;
|
||||
|
||||
/**
|
||||
* Promise that resolves when custom glyph definitions are loaded.
|
||||
*/
|
||||
let loadingPromise: Promise<void> | undefined;
|
||||
|
||||
/**
|
||||
* Begins loading the custom glyph definitions. This should be called as early as possible
|
||||
* to ensure the definitions are ready when needed.
|
||||
* @returns A promise that resolves when the definitions are loaded.
|
||||
*/
|
||||
export function loadCustomGlyphDefinitions(): Promise<void> {
|
||||
if (customGlyphDefinitions) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (!loadingPromise) {
|
||||
loadingPromise = import('./CustomGlyphDefinitions').then(module => {
|
||||
customGlyphDefinitions = module.customGlyphDefinitions;
|
||||
}).catch(err => {
|
||||
// Reset the loading promise on failure to allow retry
|
||||
loadingPromise = undefined;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
return loadingPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try drawing a custom block element or box drawing character, returning whether it was
|
||||
@@ -24,6 +54,11 @@ export function tryDrawCustomGlyph(
|
||||
devicePixelRatio: number,
|
||||
backgroundColor?: string
|
||||
): boolean {
|
||||
// If definitions are not loaded yet, return false to fall back to font rendering
|
||||
if (!customGlyphDefinitions) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const unifiedCharDefinition = customGlyphDefinitions[c];
|
||||
if (unifiedCharDefinition) {
|
||||
// Normalize to array for uniform handling
|
||||
|
||||
+15
-4
@@ -26,7 +26,10 @@ const commonOptions = {
|
||||
target: 'es2021',
|
||||
sourcemap: true,
|
||||
treeShaking: true,
|
||||
splitting: true,
|
||||
chunkNames: 'chunks/[name]-[hash]',
|
||||
logLevel: 'warning',
|
||||
outExtension: { '.js': '.mjs' },
|
||||
};
|
||||
|
||||
/** @type {esbuild.BuildOptions} */
|
||||
@@ -103,7 +106,8 @@ if (config.addon) {
|
||||
bundleConfig = {
|
||||
...bundleConfig,
|
||||
entryPoints: [`addons/addon-${config.addon}/src/${getAddonEntryPoint(config.addon)}.ts`],
|
||||
outfile: `addons/addon-${config.addon}/lib/addon-${config.addon}.mjs`,
|
||||
outdir: `addons/addon-${config.addon}/lib`,
|
||||
entryNames: `addon-${config.addon}`,
|
||||
};
|
||||
outConfig = {
|
||||
...outConfig,
|
||||
@@ -128,7 +132,8 @@ if (config.addon) {
|
||||
bundleConfig = {
|
||||
...bundleConfig,
|
||||
entryPoints: [`demo/client/client.ts`],
|
||||
outfile: 'demo/dist/client-bundle.js',
|
||||
outdir: 'demo/dist',
|
||||
entryNames: 'client-bundle',
|
||||
external: ['util', 'os', 'fs', 'path', 'stream', 'Terminal'],
|
||||
alias: {
|
||||
// Library ESM imports
|
||||
@@ -164,6 +169,10 @@ if (config.addon) {
|
||||
format: 'cjs',
|
||||
platform: 'node',
|
||||
external: ['node-pty'],
|
||||
// Splitting is not compatible with cjs format
|
||||
splitting: false,
|
||||
// Override the .mjs extension from commonOptions
|
||||
outExtension: {},
|
||||
}
|
||||
skipOut = true;
|
||||
skipOutTest = true;
|
||||
@@ -171,7 +180,8 @@ if (config.addon) {
|
||||
bundleConfig = {
|
||||
...bundleConfig,
|
||||
entryPoints: [`src/headless/public/Terminal.ts`],
|
||||
outfile: `headless/lib-headless/xterm-headless.mjs`
|
||||
outdir: `headless/lib-headless`,
|
||||
entryNames: 'xterm-headless',
|
||||
};
|
||||
outConfig = {
|
||||
...outConfig,
|
||||
@@ -183,7 +193,8 @@ if (config.addon) {
|
||||
bundleConfig = {
|
||||
...bundleConfig,
|
||||
entryPoints: [`src/browser/public/Terminal.ts`],
|
||||
outfile: `lib/xterm.mjs`
|
||||
outdir: `lib`,
|
||||
entryNames: 'xterm',
|
||||
};
|
||||
outConfig = {
|
||||
...outConfig,
|
||||
|
||||
+1
-1
@@ -23,6 +23,6 @@
|
||||
<div id="sidebar" class="grid">
|
||||
</div>
|
||||
</div>
|
||||
<script src="dist/client-bundle.js" defer ></script>
|
||||
<script src="dist/client-bundle.mjs" type="module" defer ></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -18,6 +18,6 @@
|
||||
</head>
|
||||
<body id="test">
|
||||
<div id="terminal-container"></div>
|
||||
<script src="/dist/client-bundle.js" defer></script>
|
||||
<script src="/dist/client-bundle.mjs" type="module" defer></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -28,7 +28,7 @@ import { OscLinkProvider } from 'browser/OscLinkProvider';
|
||||
import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal } from 'browser/Types';
|
||||
import { Viewport } from 'browser/Viewport';
|
||||
import { BufferDecorationRenderer } from 'browser/decorations/BufferDecorationRenderer';
|
||||
import { OverviewRulerRenderer } from 'browser/decorations/OverviewRulerRenderer';
|
||||
import type { OverviewRulerRenderer } from 'browser/decorations/OverviewRulerRenderer';
|
||||
import { CompositionHelper } from 'browser/input/CompositionHelper';
|
||||
import { DomRenderer } from 'browser/renderer/dom/DomRenderer';
|
||||
import { IRenderer } from 'browser/renderer/shared/Types';
|
||||
@@ -53,12 +53,34 @@ import { toRgbString } from 'common/input/XParseColor';
|
||||
import { DecorationService } from 'common/services/DecorationService';
|
||||
import { IDecorationService } from 'common/services/Services';
|
||||
import { WindowsOptionsReportType } from '../common/InputHandler';
|
||||
import { AccessibilityManager } from './AccessibilityManager';
|
||||
import type { AccessibilityManager } from './AccessibilityManager';
|
||||
import { Linkifier } from './Linkifier';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { addDisposableListener } from 'vs/base/browser/dom';
|
||||
import { MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
/**
|
||||
* Lazily loaded AccessibilityManager module.
|
||||
*/
|
||||
let accessibilityManagerModule: Promise<typeof import('./AccessibilityManager')> | undefined;
|
||||
function loadAccessibilityManager(): Promise<typeof import('./AccessibilityManager')> {
|
||||
if (!accessibilityManagerModule) {
|
||||
accessibilityManagerModule = import('./AccessibilityManager');
|
||||
}
|
||||
return accessibilityManagerModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily loaded OverviewRulerRenderer module.
|
||||
*/
|
||||
let overviewRulerRendererModule: Promise<typeof import('browser/decorations/OverviewRulerRenderer')> | undefined;
|
||||
function loadOverviewRulerRenderer(): Promise<typeof import('browser/decorations/OverviewRulerRenderer')> {
|
||||
if (!overviewRulerRendererModule) {
|
||||
overviewRulerRendererModule = import('browser/decorations/OverviewRulerRenderer');
|
||||
}
|
||||
return overviewRulerRendererModule;
|
||||
}
|
||||
|
||||
export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
||||
public textarea: HTMLTextAreaElement | undefined;
|
||||
public element: HTMLElement | undefined;
|
||||
@@ -277,7 +299,14 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
||||
private _handleScreenReaderModeOptionChange(value: boolean): void {
|
||||
if (value) {
|
||||
if (!this._accessibilityManager.value && this._renderService) {
|
||||
this._accessibilityManager.value = this._instantiationService.createInstance(AccessibilityManager, this);
|
||||
loadAccessibilityManager().then(module => {
|
||||
// Check again after async load in case option changed
|
||||
if (this.options.screenReaderMode && !this._accessibilityManager.value && this._renderService) {
|
||||
this._accessibilityManager.value = this._instantiationService.createInstance(module.AccessibilityManager, this);
|
||||
}
|
||||
}).catch(() => {
|
||||
// Failed to load accessibility manager module
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this._accessibilityManager.clear();
|
||||
@@ -588,16 +617,34 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal {
|
||||
if (this.options.screenReaderMode) {
|
||||
// Note that this must be done *after* the renderer is created in order to
|
||||
// ensure the correct order of the dprchange event
|
||||
this._accessibilityManager.value = this._instantiationService.createInstance(AccessibilityManager, this);
|
||||
loadAccessibilityManager().then(module => {
|
||||
if (this.options.screenReaderMode && !this._accessibilityManager.value && this._renderService) {
|
||||
this._accessibilityManager.value = this._instantiationService.createInstance(module.AccessibilityManager, this);
|
||||
}
|
||||
}).catch(() => {
|
||||
// Failed to load accessibility manager module
|
||||
});
|
||||
}
|
||||
this._register(this.optionsService.onSpecificOptionChange('screenReaderMode', e => this._handleScreenReaderModeOptionChange(e)));
|
||||
|
||||
if (this.options.overviewRuler.width) {
|
||||
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
||||
loadOverviewRulerRenderer().then(module => {
|
||||
if (this.options.overviewRuler.width && !this._overviewRulerRenderer && this._viewportElement && this.screenElement) {
|
||||
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(module.OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
||||
}
|
||||
}).catch(() => {
|
||||
// Failed to load overview ruler renderer module
|
||||
});
|
||||
}
|
||||
this.optionsService.onSpecificOptionChange('overviewRuler', value => {
|
||||
if (!this._overviewRulerRenderer && value && this._viewportElement && this.screenElement) {
|
||||
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
||||
loadOverviewRulerRenderer().then(module => {
|
||||
if (!this._overviewRulerRenderer && this.options.overviewRuler.width && this._viewportElement && this.screenElement) {
|
||||
this._overviewRulerRenderer = this._register(this._instantiationService.createInstance(module.OverviewRulerRenderer, this._viewportElement, this.screenElement));
|
||||
}
|
||||
}).catch(() => {
|
||||
// Failed to load overview ruler renderer module
|
||||
});
|
||||
}
|
||||
});
|
||||
// Measure the character size
|
||||
|
||||
Reference in New Issue
Block a user