diff --git a/addons/addon-search/src/DecorationManager.ts b/addons/addon-search/src/DecorationManager.ts index a8ec12017..3da46cc52 100644 --- a/addons/addon-search/src/DecorationManager.ts +++ b/addons/addon-search/src/DecorationManager.ts @@ -131,6 +131,9 @@ export class DecorationManager extends Disposable { const decorations: IDecoration[] = []; for (const range of decorationRanges) { const marker = this._terminal.registerMarker(range[0]); + if (!marker) { + continue; + } const decoration = this._terminal.registerDecoration({ marker, x: range[1], diff --git a/demo/client/components/window/testWindow.ts b/demo/client/components/window/testWindow.ts index 1ea6b3e67..bb03bcf73 100644 --- a/demo/client/components/window/testWindow.ts +++ b/demo/client/components/window/testWindow.ts @@ -753,7 +753,7 @@ async function loadTestLongLines(term: Terminal, addons: AddonCollection): Promi function addDecoration(term: Terminal, dim: number = 1): void { term.options.scrollbar = { ...(term.options.scrollbar ?? {}), width: 14, overviewRuler: term.options.scrollbar?.overviewRuler ?? {} }; - const marker = term.registerMarker(1); + const marker = term.registerMarker(1)!; const decoration = term.registerDecoration({ marker, height: dim, @@ -770,14 +770,14 @@ function addDecoration(term: Terminal, dim: number = 1): void { function addOverviewRuler(term: Terminal): void { term.options.scrollbar = { ...(term.options.scrollbar ?? {}), width: 14, overviewRuler: term.options.scrollbar?.overviewRuler ?? {} }; - term.registerDecoration({ marker: term.registerMarker(1), overviewRulerOptions: { color: '#ef2929' } }); - term.registerDecoration({ marker: term.registerMarker(3), overviewRulerOptions: { color: '#8ae234' } }); - term.registerDecoration({ marker: term.registerMarker(5), overviewRulerOptions: { color: '#729fcf' } }); - term.registerDecoration({ marker: term.registerMarker(7), overviewRulerOptions: { color: '#ef2929', position: 'left' } }); - term.registerDecoration({ marker: term.registerMarker(7), overviewRulerOptions: { color: '#8ae234', position: 'center' } }); - term.registerDecoration({ marker: term.registerMarker(7), overviewRulerOptions: { color: '#729fcf', position: 'right' } }); - term.registerDecoration({ marker: term.registerMarker(10), overviewRulerOptions: { color: '#8ae234', position: 'center' } }); - term.registerDecoration({ marker: term.registerMarker(10), overviewRulerOptions: { color: '#ffffff80', position: 'full' } }); + term.registerDecoration({ marker: term.registerMarker(1)!, overviewRulerOptions: { color: '#ef2929' } }); + term.registerDecoration({ marker: term.registerMarker(3)!, overviewRulerOptions: { color: '#8ae234' } }); + term.registerDecoration({ marker: term.registerMarker(5)!, overviewRulerOptions: { color: '#729fcf' } }); + term.registerDecoration({ marker: term.registerMarker(7)!, overviewRulerOptions: { color: '#ef2929', position: 'left' } }); + term.registerDecoration({ marker: term.registerMarker(7)!, overviewRulerOptions: { color: '#8ae234', position: 'center' } }); + term.registerDecoration({ marker: term.registerMarker(7)!, overviewRulerOptions: { color: '#729fcf', position: 'right' } }); + term.registerDecoration({ marker: term.registerMarker(10)!, overviewRulerOptions: { color: '#8ae234', position: 'center' } }); + term.registerDecoration({ marker: term.registerMarker(10)!, overviewRulerOptions: { color: '#ffffff80', position: 'full' } }); } let decorationStressTestDecorations: IDisposable[] | undefined; @@ -795,7 +795,7 @@ function decorationStressTest(term: Terminal): void { for (let y = 0; y < term.buffer.active.length; y++) { const cursorOffsetY = y - cursorY; const decoration = term.registerDecoration({ - marker: term.registerMarker(cursorOffsetY), + marker: term.registerMarker(cursorOffsetY)!, x, width: 4, backgroundColor: '#FF0000', diff --git a/src/browser/CoreBrowserTerminal.ts b/src/browser/CoreBrowserTerminal.ts index e44b1717e..f22f5ac8e 100644 --- a/src/browser/CoreBrowserTerminal.ts +++ b/src/browser/CoreBrowserTerminal.ts @@ -768,7 +768,12 @@ export class CoreBrowserTerminal extends CoreTerminal implements ITerminal { return this.buffer.markers; } - public registerMarker(cursorYOffset: number): IMarker { + public registerMarker(cursorYOffset: number): IMarker | undefined { + // Disallow markers on the alt buffer + if (this.buffer !== this.buffers.normal) { + return; + } + return this.buffer.addMarker(this.buffer.ybase + this.buffer.y + cursorYOffset); } diff --git a/src/browser/Terminal.test.ts b/src/browser/Terminal.test.ts index d359fa28c..bf9f616e2 100644 --- a/src/browser/Terminal.test.ts +++ b/src/browser/Terminal.test.ts @@ -1146,6 +1146,16 @@ describe('Terminal', () => { assert.equal(termConverting.buffer.lines.get(1)!.translateToString(true), 'World'); }); + describe('registerMarker', () => { + it('should return undefined on the alt buffer', async () => { + assert.isDefined(term.registerMarker(0)); + await term.writeP('\x1b[?47h'); + assert.isUndefined(term.registerMarker(0)); + await term.writeP('\x1b[?47l'); + assert.isDefined(term.registerMarker(0)); + }); + }); + // FIXME: move to common/CoreTerminal.test once the trimming is moved over describe('marker lifecycle', () => { // create a 10x5 terminal with markers on every line diff --git a/src/browser/public/Terminal.ts b/src/browser/public/Terminal.ts index 75aada048..b7e3c6c2c 100644 --- a/src/browser/public/Terminal.ts +++ b/src/browser/public/Terminal.ts @@ -166,7 +166,7 @@ export class Terminal extends Disposable implements ITerminalApi { public deregisterCharacterJoiner(joinerId: number): void { this._core.deregisterCharacterJoiner(joinerId); } - public registerMarker(cursorYOffset: number = 0): IMarker { + public registerMarker(cursorYOffset: number = 0): IMarker | undefined { this._verifyIntegers(cursorYOffset); return this._core.registerMarker(cursorYOffset); } diff --git a/src/headless/public/Terminal.test.ts b/src/headless/public/Terminal.test.ts index 0c4739744..21837d3a8 100644 --- a/src/headless/public/Terminal.test.ts +++ b/src/headless/public/Terminal.test.ts @@ -419,6 +419,18 @@ describe('Headless API Tests', function (): void { strictEqual(term.buffer.normal.getLine(0)!.translateToString(), 'norm '); strictEqual(term.buffer.alternate.getLine(0), undefined); }); + + it('registerMarker returns undefined on the alt buffer', async () => { + term = new Terminal({ cols: 5, allowProposedApi: true }); + strictEqual(term.buffer.active.type, 'normal'); + strictEqual(term.registerMarker(0)!.line, 0); + await writeSync('\x1b[?47h'); + strictEqual(term.buffer.active.type, 'alternate'); + strictEqual(term.registerMarker(0), undefined); + await writeSync('\x1b[?47l'); + strictEqual(term.buffer.active.type, 'normal'); + strictEqual(term.registerMarker(0)!.line, 0); + }); }); describe('modes', () => { diff --git a/test/playwright/TestUtils.ts b/test/playwright/TestUtils.ts index 8a76c8820..7dcdbe19b 100644 --- a/test/playwright/TestUtils.ts +++ b/test/playwright/TestUtils.ts @@ -284,7 +284,7 @@ export class TerminalProxy implements ITerminalProxyCustomMethods, PlaywrightApi } public async input(data: string, wasUserInput: boolean = true): Promise { return this.evaluate(([term]) => term.input(data, wasUserInput)); } public async resize(cols: number, rows: number): Promise { return this._page.evaluate(([term, cols, rows]) => term.resize(cols, rows), [await this.getHandle(), cols, rows] as const); } - public async registerMarker(y?: number | undefined): Promise { return this._page.evaluate(([term, y]) => term.registerMarker(y), [await this.getHandle(), y] as const); } + public async registerMarker(y?: number | undefined): Promise { return this._page.evaluate(([term, y]) => term.registerMarker(y), [await this.getHandle(), y] as const); } public async registerDecoration(decorationOptions: IDecorationOptions): Promise { return this._page.evaluate(([term, decorationOptions]) => term.registerDecoration(decorationOptions), [await this.getHandle(), decorationOptions] as const); } public async clearTextureAtlas(): Promise { return this.evaluate(([term]) => term.clearTextureAtlas()); } // #endregion diff --git a/typings/xterm.d.ts b/typings/xterm.d.ts index d1ce877b9..ab26dcd63 100644 --- a/typings/xterm.d.ts +++ b/typings/xterm.d.ts @@ -1257,11 +1257,12 @@ declare module '@xterm/xterm' { deregisterCharacterJoiner(joinerId: number): void; /** - * Adds a marker to the normal buffer and returns it. + * Adds a marker to the normal buffer and returns it. If the alt buffer is + * active, undefined is returned. * @param cursorYOffset The y position offset of the marker from the cursor. * @returns The new marker or undefined. */ - registerMarker(cursorYOffset?: number): IMarker; + registerMarker(cursorYOffset?: number): IMarker | undefined; /** * Registers a decoration to the terminal.