Sync textarea with cursor. Fixes #2598

This commit is contained in:
jeanp413
2020-07-09 03:56:40 -05:00
parent dc541c2664
commit 95d01dec52
6 changed files with 35 additions and 26 deletions
+4 -4
View File
@@ -59,10 +59,10 @@
}
.xterm .xterm-helper-textarea {
/*
* HACK: to fix IE's blinking cursor
* Move textarea out of the screen to the far left, so that the cursor is not visible.
*/
padding: 0;
border: 0;
margin: 0;
/* Move textarea out of the screen to the far left, so that the cursor is not visible */
position: absolute;
opacity: 0;
left: -9999em;
-11
View File
@@ -78,17 +78,6 @@ export function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextA
textarea.style.zIndex = '1000';
textarea.focus();
// Reset the terminal textarea's styling
// Timeout needs to be long enough for click event to be handled.
setTimeout(() => {
textarea.style.position = '';
textarea.style.width = '';
textarea.style.height = '';
textarea.style.left = '';
textarea.style.top = '';
textarea.style.zIndex = '';
}, 200);
}
/**
+25 -1
View File
@@ -281,6 +281,26 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._onBlur.fire();
}
private _syncTextArea(): void {
if (!this.buffer.isCursorInViewport || this._compositionHelper!.isComposing) {
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;
// Sync the textarea to the exact position of the composition view so the IME knows where the
// text is.
this.textarea!.style.position = 'absolute';
this.textarea!.style.left = cursorLeft + 'px';
this.textarea!.style.top = cursorTop + 'px';
this.textarea!.style.width = this._charSizeService!.width + 'px';
this.textarea!.style.height = cellHeight + 'px';
this.textarea!.style.lineHeight = cellHeight + 'px';
this.textarea!.style.zIndex = '-5';
}
/**
* Initialize default behavior
*/
@@ -436,7 +456,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
this.register(this.viewport);
this.register(this.onCursorMove(() => this._renderService!.onCursorMove()));
this.register(this.onCursorMove(() => {
this._renderService!.onCursorMove();
this._syncTextArea();
}));
this.register(this.onResize(() => this._renderService!.onResize(this.cols, this.rows)));
this.register(this.onBlur(() => this._renderService!.onBlur()));
this.register(this.onFocus(() => this._renderService!.onFocus()));
+3
View File
@@ -309,6 +309,9 @@ export class MockViewport implements IViewport {
}
export class MockCompositionHelper implements ICompositionHelper {
public get isComposing(): boolean {
return false;
}
public compositionstart(): void {
throw new Error('Method not implemented.');
}
+1
View File
@@ -87,6 +87,7 @@ export type CustomKeyEventHandler = (event: KeyboardEvent) => boolean;
export type LineData = CharData[];
export interface ICompositionHelper {
readonly isComposing: boolean;
compositionstart(): void;
compositionupdate(ev: CompositionEvent): void;
compositionend(): void;
+2 -10
View File
@@ -22,6 +22,7 @@ export class CompositionHelper {
* IME. This variable determines whether the compositionText should be displayed on the UI.
*/
private _isComposing: boolean;
public get isComposing(): boolean { return this._isComposing; }
/**
* The position within the input textarea's value of the current composition.
@@ -118,7 +119,6 @@ export class CompositionHelper {
private _finalizeComposition(waitForPropagation: boolean): void {
this._compositionView.classList.remove('active');
this._isComposing = false;
this._clearTextareaPosition();
if (!waitForPropagation) {
// Cancel any delayed composition send requests and send the input immediately.
@@ -207,6 +207,7 @@ export class CompositionHelper {
// Sync the textarea to the exact position of the composition view so the IME knows where the
// text is.
const compositionViewBounds = this._compositionView.getBoundingClientRect();
this._textarea.style.position = 'absolute';
this._textarea.style.left = cursorLeft + 'px';
this._textarea.style.top = cursorTop + 'px';
this._textarea.style.width = compositionViewBounds.width + 'px';
@@ -218,13 +219,4 @@ export class CompositionHelper {
setTimeout(() => this.updateCompositionElements(true), 0);
}
}
/**
* Clears the textarea's position so that the cursor does not blink on IE.
* @private
*/
private _clearTextareaPosition(): void {
this._textarea.style.left = '';
this._textarea.style.top = '';
}
}