Fixes #141725: Avoid flickering by reusing the previous presentation for the <textarea> in case it starts spanning multiple tokens while doing composition

This commit is contained in:
Alex Dima 2022-02-18 09:46:08 +01:00
parent 332bb6ccca
commit 2e8d14275c
No known key found for this signature in database
GPG key ID: 39563C1504FDD0C9

View file

@ -47,6 +47,14 @@ class VisibleTextAreaData {
public visibleTextareaStart: HorizontalPosition | null = null;
public visibleTextareaEnd: HorizontalPosition | null = null;
/**
* When doing composition, the currently composed text might be split up into
* multiple tokens, then merged again into a single token, etc. Here we attempt
* to keep the presentation of the <textarea> stable by using the previous used
* style if multiple tokens come into play. This avoids flickering.
*/
private _previousPresentation: ITokenPresentation | null = null;
constructor(
private readonly _context: ViewContext,
public readonly modelLineNumber: number,
@ -72,6 +80,22 @@ class VisibleTextAreaData {
this.visibleTextareaEnd = null;
}
}
updatePresentation(tokenPresentation: ITokenPresentation | null): ITokenPresentation {
if (tokenPresentation) {
this._previousPresentation = tokenPresentation;
}
if (!this._previousPresentation) {
this._previousPresentation = {
foreground: ColorId.DefaultForeground,
italic: false,
bold: false,
underline: false,
strikethrough: false,
};
}
return this._previousPresentation;
}
}
const canUseZeroSizeTextarea = (browser.isFirefox);
@ -644,19 +668,10 @@ export class TextAreaHandler extends ViewPart {
const viewLineData = this._context.viewModel.getViewLineData(startPosition.lineNumber);
const startTokenIndex = viewLineData.tokens.findTokenIndexAtOffset(startPosition.column - 1);
const endTokenIndex = viewLineData.tokens.findTokenIndexAtOffset(endPosition.column - 1);
let presentation: ITokenPresentation;
if (startTokenIndex === endTokenIndex) {
presentation = viewLineData.tokens.getPresentation(startTokenIndex);
} else {
// if the textarea spans multiple tokens, then use default styles
presentation = {
foreground: ColorId.DefaultForeground,
italic: false,
bold: false,
underline: false,
strikethrough: false,
};
}
const textareaSpansSingleToken = (startTokenIndex === endTokenIndex);
const presentation = this._visibleTextArea.updatePresentation(
(textareaSpansSingleToken ? viewLineData.tokens.getPresentation(startTokenIndex) : null)
);
this.textArea.domNode.scrollTop = lineCount * this._lineHeight;
this.textArea.domNode.scrollLeft = scrollLeft;