From acf53f69e0cb0271fecd93dc9b0535a1f24fe2ef Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 2 Aug 2023 11:18:00 -0700 Subject: [PATCH 1/3] Ensure viewport is correctly reset on term.reset Part of #4603 --- src/browser/Terminal.ts | 2 +- src/browser/TestUtils.test.ts | 3 +++ src/browser/Types.d.ts | 3 ++- src/browser/Viewport.ts | 14 +++++++++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 3f49c82533..c4f8f26e7c 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -1255,13 +1255,13 @@ export class Terminal extends CoreTerminal implements ITerminal { super.reset(); this._selectionService?.reset(); this._decorationService.reset(); + this.viewport?.reset(); // reattach this._customKeyEventHandler = customKeyEventHandler; // do a full screen refresh this.refresh(0, this.rows - 1); - this.viewport?.syncScrollArea(); } public clearTextureAtlas(): void { diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index c04c9af202..61918fe15d 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -324,6 +324,9 @@ export class MockViewport implements IViewport { public scrollLines(disp: number): void { this._onRequestScrollLines.fire({ amount: disp, suppressScrollEvent: false }); } + public reset(): void { + throw new Error('Method not implemented.'); + } } export class MockCompositionHelper implements ICompositionHelper { diff --git a/src/browser/Types.d.ts b/src/browser/Types.d.ts index 42d56c068c..5337a1692e 100644 --- a/src/browser/Types.d.ts +++ b/src/browser/Types.d.ts @@ -161,13 +161,14 @@ export interface IPartialColorSet { export interface IViewport extends IDisposable { scrollBarWidth: number; readonly onRequestScrollLines: IEvent<{ amount: number, suppressScrollEvent: boolean }>; - syncScrollArea(immediate?: boolean): void; + syncScrollArea(immediate?: boolean, force?: boolean): void; getLinesScrolled(ev: WheelEvent): number; getBufferElements(startLine: number, endLine?: number): { bufferElements: HTMLElement[], cursorElement?: HTMLElement }; handleWheel(ev: WheelEvent): boolean; handleTouchStart(ev: TouchEvent): void; handleTouchMove(ev: TouchEvent): boolean; scrollLines(disp: number): void; // todo api name? + reset(): void; } export interface ILinkifierEvent { diff --git a/src/browser/Viewport.ts b/src/browser/Viewport.ts index a30228a42a..48e973418d 100644 --- a/src/browser/Viewport.ts +++ b/src/browser/Viewport.ts @@ -81,13 +81,25 @@ export class Viewport extends Disposable implements IViewport { this.register(this._optionsService.onSpecificOptionChange('scrollback', () => this.syncScrollArea())); // Perform this async to ensure the ICharSizeService is ready. - setTimeout(() => this.syncScrollArea(), 0); + setTimeout(() => this.syncScrollArea()); } private _handleThemeChange(colors: ReadonlyColorSet): void { this._viewportElement.style.backgroundColor = colors.background.css; } + public reset(): void { + this._currentRowHeight = 0; + this._currentDeviceCellHeight = 0; + this._lastRecordedBufferLength = 0; + this._lastRecordedViewportHeight = 0; + this._lastRecordedBufferHeight = 0; + this._lastTouchY = 0; + this._lastScrollTop = 0; + // Sync on next animation frame to ensure the new terminal state is used + this._coreBrowserService.window.requestAnimationFrame(() => this.syncScrollArea()); + } + /** * Refreshes row height, setting line-height, viewport height and scroll area height if * necessary. From 91c08ed48e66722352f623a2029ac5c007cba621 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 2 Aug 2023 11:30:43 -0700 Subject: [PATCH 2/3] Fix clear leaving viewport in a bad state Fixes #4603 --- src/browser/Terminal.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index c4f8f26e7c..f0ce46947e 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -1230,8 +1230,11 @@ export class Terminal extends CoreTerminal implements ITerminal { for (let i = 1; i < this.rows; i++) { this.buffer.lines.push(this.buffer.getBlankLine(DEFAULT_ATTR_DATA)); } - this.refresh(0, this.rows - 1); + // IMPORTANT: Fire scroll event before viewport is reset. This ensures embedders get the clear + // scroll event and that the viewport's state will be valid for immediate writes. this._onScroll.fire({ position: this.buffer.ydisp, source: ScrollSource.TERMINAL }); + this.viewport?.reset(); + this.refresh(0, this.rows - 1); } /** From d2031955ec950912f7e52b7f03602e151d02b921 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Wed, 2 Aug 2023 11:42:40 -0700 Subject: [PATCH 3/3] Remove error from MockViewport.reset --- src/browser/TestUtils.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/browser/TestUtils.test.ts b/src/browser/TestUtils.test.ts index 61918fe15d..2015d04637 100644 --- a/src/browser/TestUtils.test.ts +++ b/src/browser/TestUtils.test.ts @@ -325,7 +325,6 @@ export class MockViewport implements IViewport { this._onRequestScrollLines.fire({ amount: disp, suppressScrollEvent: false }); } public reset(): void { - throw new Error('Method not implemented.'); } }