From de334ea116efbfe8badd940a4ab808619835e3f1 Mon Sep 17 00:00:00 2001 From: kena0ki Date: Wed, 31 Mar 2021 23:32:53 +0900 Subject: [PATCH 1/6] Use RenderService.dimensions instead of CharSizeService for textarea position --- src/browser/Terminal.ts | 32 ++++++++++++--------- src/browser/input/CompositionHelper.test.ts | 4 +-- src/browser/input/CompositionHelper.ts | 17 +++++++---- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 2eba4027..95d74254 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -297,19 +297,23 @@ export class Terminal extends CoreTerminal implements ITerminal { } private _syncTextArea(): void { - if (!this.textarea || !this.buffer.isCursorInViewport || this._compositionHelper!.isComposing) { + if (!this.textarea || !this.buffer.isCursorInViewport || this._compositionHelper!.isComposing || !this._renderService) { return; } - - const cellHeight = Math.ceil(this._charSizeService!.height * this.optionsService.options.lineHeight); - const cursorTop = this._bufferService.buffer.y * cellHeight; - const cursorLeft = this._bufferService.buffer.x * this._charSizeService!.width; + const cursorY = this.buffer.ybase + this.buffer.y; + const viewportRelativeCursorY = cursorY - this.buffer.ydisp; + const cursorX = Math.min(this.buffer.x, this.cols - 1); + const cellHeight = this._renderService.dimensions.actualCellHeight; + const width = this.buffer.lines.get(cursorY)!.getWidth(cursorX); + const cellWidth = this._renderService.dimensions.actualCellWidth * width; + const cursorTop = viewportRelativeCursorY * this._renderService.dimensions.actualCellHeight; + const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth; // Sync the textarea to the exact position of the composition view so the IME knows where the // text is. this.textarea.style.left = cursorLeft + 'px'; this.textarea.style.top = cursorTop + 'px'; - this.textarea.style.width = this._charSizeService!.width + 'px'; + this.textarea.style.width = cellWidth +'px'; this.textarea.style.height = cellHeight + 'px'; this.textarea.style.lineHeight = cellHeight + 'px'; this.textarea.style.zIndex = '-5'; @@ -438,14 +442,6 @@ export class Terminal extends CoreTerminal implements ITerminal { this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer); this._instantiationService.setService(ICharSizeService, this._charSizeService); - this._compositionView = document.createElement('div'); - this._compositionView.classList.add('composition-view'); - this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView); - this._helperContainer.appendChild(this._compositionView); - - // Performance: Add viewport and helper elements from the fragment - this.element.appendChild(fragment); - this._theme = this.options.theme || this._theme; this._colorManager = new ColorManager(document, this.options.allowTransparency); this.register(this.optionsService.onOptionChange(e => this._colorManager!.onOptionsChange(e))); @@ -457,6 +453,14 @@ export class Terminal extends CoreTerminal implements ITerminal { this.register(this._renderService.onRenderedBufferChange(e => this._onRender.fire(e))); this.onResize(e => this._renderService!.resize(e.cols, e.rows)); + this._compositionView = document.createElement('div'); + this._compositionView.classList.add('composition-view'); + this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView); + this._helperContainer.appendChild(this._compositionView); + + // Performance: Add viewport and helper elements from the fragment + this.element.appendChild(fragment); + this._soundService = this._instantiationService.createInstance(SoundService); this._instantiationService.setService(ISoundService, this._soundService); this._mouseService = this._instantiationService.createInstance(MouseService); diff --git a/src/browser/input/CompositionHelper.test.ts b/src/browser/input/CompositionHelper.test.ts index b9a4f668..080c9c47 100644 --- a/src/browser/input/CompositionHelper.test.ts +++ b/src/browser/input/CompositionHelper.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { CompositionHelper } from 'browser/input/CompositionHelper'; -import { MockCharSizeService } from 'browser/TestUtils.test'; +import { MockCharSizeService, MockRenderService } from 'browser/TestUtils.test'; import { MockCoreService, MockBufferService, MockOptionsService } from 'common/TestUtils.test'; describe('CompositionHelper', () => { @@ -42,7 +42,7 @@ describe('CompositionHelper', () => { }; handledText = ''; const bufferService = new MockBufferService(10, 5); - compositionHelper = new CompositionHelper(textarea, compositionView, bufferService, new MockOptionsService(), new MockCharSizeService(10, 10), coreService); + compositionHelper = new CompositionHelper(textarea, compositionView, bufferService, new MockOptionsService(), new MockCharSizeService(10, 10), coreService, new MockRenderService()); }); describe('Input', () => { diff --git a/src/browser/input/CompositionHelper.ts b/src/browser/input/CompositionHelper.ts index 85cfc3b6..e5389af4 100644 --- a/src/browser/input/CompositionHelper.ts +++ b/src/browser/input/CompositionHelper.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ICharSizeService } from 'browser/services/Services'; +import { ICharSizeService, IRenderService } from 'browser/services/Services'; import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services'; interface IPosition { @@ -46,7 +46,8 @@ export class CompositionHelper { @IBufferService private readonly _bufferService: IBufferService, @IOptionsService private readonly _optionsService: IOptionsService, @ICharSizeService private readonly _charSizeService: ICharSizeService, - @ICoreService private readonly _coreService: ICoreService + @ICoreService private readonly _coreService: ICoreService, + @IRenderService private readonly _renderService: IRenderService ) { this._isComposing = false; this._isSendingComposition = false; @@ -202,14 +203,18 @@ export class CompositionHelper { * necessary as the IME events across browsers are not consistently triggered. */ public updateCompositionElements(dontRecurse?: boolean): void { - if (!this._isComposing) { + if (!this._isComposing || !this._renderService) { return; } if (this._bufferService.buffer.isCursorInViewport) { - const cellHeight = Math.ceil(this._charSizeService.height * this._optionsService.options.lineHeight); - const cursorTop = this._bufferService.buffer.y * cellHeight; - const cursorLeft = this._bufferService.buffer.x * this._charSizeService.width; + const cursorY = this._bufferService.buffer.ybase + this._bufferService.buffer.y; + const viewportRelativeCursorY = cursorY - this._bufferService.buffer.ydisp; + const cursorX = Math.min(this._bufferService.buffer.x, this._bufferService.cols - 1); + + const cellHeight = this._renderService.dimensions.actualCellHeight; + const cursorTop = viewportRelativeCursorY * this._renderService.dimensions.actualCellHeight; + const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth; this._compositionView.style.left = cursorLeft + 'px'; this._compositionView.style.top = cursorTop + 'px'; From a15f61bb8540cd7817170b735bee9a454eaf12a5 Mon Sep 17 00:00:00 2001 From: kena0ki Date: Thu, 1 Apr 2021 00:11:30 +0900 Subject: [PATCH 2/6] Remove non-null assertion --- src/browser/Terminal.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 95d74254..371f5549 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -304,7 +304,9 @@ export class Terminal extends CoreTerminal implements ITerminal { const viewportRelativeCursorY = cursorY - this.buffer.ydisp; const cursorX = Math.min(this.buffer.x, this.cols - 1); const cellHeight = this._renderService.dimensions.actualCellHeight; - const width = this.buffer.lines.get(cursorY)!.getWidth(cursorX); + const bufferLine = this.buffer.lines.get(cursorY); + if (!bufferLine) return; + const width = bufferLine.getWidth(cursorX); const cellWidth = this._renderService.dimensions.actualCellWidth * width; const cursorTop = viewportRelativeCursorY * this._renderService.dimensions.actualCellHeight; const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth; From e9e716964e1a24758132ac92e22276147ced54ed Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 1 Apr 2021 08:19:12 -0700 Subject: [PATCH 3/6] Remove now unneeded CharSizeService --- src/browser/input/CompositionHelper.test.ts | 4 ++-- src/browser/input/CompositionHelper.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/browser/input/CompositionHelper.test.ts b/src/browser/input/CompositionHelper.test.ts index 080c9c47..c722570b 100644 --- a/src/browser/input/CompositionHelper.test.ts +++ b/src/browser/input/CompositionHelper.test.ts @@ -5,7 +5,7 @@ import { assert } from 'chai'; import { CompositionHelper } from 'browser/input/CompositionHelper'; -import { MockCharSizeService, MockRenderService } from 'browser/TestUtils.test'; +import { MockRenderService } from 'browser/TestUtils.test'; import { MockCoreService, MockBufferService, MockOptionsService } from 'common/TestUtils.test'; describe('CompositionHelper', () => { @@ -42,7 +42,7 @@ describe('CompositionHelper', () => { }; handledText = ''; const bufferService = new MockBufferService(10, 5); - compositionHelper = new CompositionHelper(textarea, compositionView, bufferService, new MockOptionsService(), new MockCharSizeService(10, 10), coreService, new MockRenderService()); + compositionHelper = new CompositionHelper(textarea, compositionView, bufferService, new MockOptionsService(), coreService, new MockRenderService()); }); describe('Input', () => { diff --git a/src/browser/input/CompositionHelper.ts b/src/browser/input/CompositionHelper.ts index e5389af4..d2626e2c 100644 --- a/src/browser/input/CompositionHelper.ts +++ b/src/browser/input/CompositionHelper.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { ICharSizeService, IRenderService } from 'browser/services/Services'; +import { IRenderService } from 'browser/services/Services'; import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services'; interface IPosition { @@ -45,7 +45,6 @@ export class CompositionHelper { private readonly _compositionView: HTMLElement, @IBufferService private readonly _bufferService: IBufferService, @IOptionsService private readonly _optionsService: IOptionsService, - @ICharSizeService private readonly _charSizeService: ICharSizeService, @ICoreService private readonly _coreService: ICoreService, @IRenderService private readonly _renderService: IRenderService ) { From b62a64519f567081f327c34c01a056eb9edcdcd4 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 1 Apr 2021 08:23:18 -0700 Subject: [PATCH 4/6] Use buffer y for relative cursor pos --- src/browser/input/CompositionHelper.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/browser/input/CompositionHelper.ts b/src/browser/input/CompositionHelper.ts index d2626e2c..65a5d672 100644 --- a/src/browser/input/CompositionHelper.ts +++ b/src/browser/input/CompositionHelper.ts @@ -207,12 +207,10 @@ export class CompositionHelper { } if (this._bufferService.buffer.isCursorInViewport) { - const cursorY = this._bufferService.buffer.ybase + this._bufferService.buffer.y; - const viewportRelativeCursorY = cursorY - this._bufferService.buffer.ydisp; const cursorX = Math.min(this._bufferService.buffer.x, this._bufferService.cols - 1); const cellHeight = this._renderService.dimensions.actualCellHeight; - const cursorTop = viewportRelativeCursorY * this._renderService.dimensions.actualCellHeight; + const cursorTop = this._bufferService.buffer.y * this._renderService.dimensions.actualCellHeight; const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth; this._compositionView.style.left = cursorLeft + 'px'; From 05516750b5ac832147c7153f5db1f79d7f941508 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 1 Apr 2021 08:23:35 -0700 Subject: [PATCH 5/6] Remove RenderService check, it must be passed to ctor --- src/browser/input/CompositionHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/input/CompositionHelper.ts b/src/browser/input/CompositionHelper.ts index 65a5d672..8a204831 100644 --- a/src/browser/input/CompositionHelper.ts +++ b/src/browser/input/CompositionHelper.ts @@ -202,7 +202,7 @@ export class CompositionHelper { * necessary as the IME events across browsers are not consistently triggered. */ public updateCompositionElements(dontRecurse?: boolean): void { - if (!this._isComposing || !this._renderService) { + if (!this._isComposing) { return; } From 7b920adbe9ace642e4188a7c60412c9cd7d620d5 Mon Sep 17 00:00:00 2001 From: Daniel Imms <2193314+Tyriar@users.noreply.github.com> Date: Thu, 1 Apr 2021 08:26:35 -0700 Subject: [PATCH 6/6] Tidy up syncTextArea --- src/browser/Terminal.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/browser/Terminal.ts b/src/browser/Terminal.ts index 371f5549..f95013cd 100644 --- a/src/browser/Terminal.ts +++ b/src/browser/Terminal.ts @@ -301,21 +301,22 @@ export class Terminal extends CoreTerminal implements ITerminal { return; } const cursorY = this.buffer.ybase + this.buffer.y; - const viewportRelativeCursorY = cursorY - this.buffer.ydisp; + const bufferLine = this.buffer.lines.get(cursorY); + if (!bufferLine) { + return; + } const cursorX = Math.min(this.buffer.x, this.cols - 1); const cellHeight = this._renderService.dimensions.actualCellHeight; - const bufferLine = this.buffer.lines.get(cursorY); - if (!bufferLine) return; const width = bufferLine.getWidth(cursorX); const cellWidth = this._renderService.dimensions.actualCellWidth * width; - const cursorTop = viewportRelativeCursorY * this._renderService.dimensions.actualCellHeight; + const cursorTop = this.buffer.y * this._renderService.dimensions.actualCellHeight; const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth; // Sync the textarea to the exact position of the composition view so the IME knows where the // text is. this.textarea.style.left = cursorLeft + 'px'; this.textarea.style.top = cursorTop + 'px'; - this.textarea.style.width = cellWidth +'px'; + this.textarea.style.width = cellWidth + 'px'; this.textarea.style.height = cellHeight + 'px'; this.textarea.style.lineHeight = cellHeight + 'px'; this.textarea.style.zIndex = '-5';