Skip to content

Commit 372db60

Browse files
authored
fix cursor position issues (microsoft#175160)
1 parent 3c9f409 commit 372db60

File tree

1 file changed

+36
-15
lines changed

1 file changed

+36
-15
lines changed

src/vs/workbench/contrib/terminal/browser/xterm/xtermTerminal.ts

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import type { SerializeAddon as SerializeAddonType } from 'xterm-addon-serialize
1212
import { IXtermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private';
1313
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
1414
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
15-
import { DisposableStore } from 'vs/base/common/lifecycle';
15+
import { DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
1616
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
1717
import { IShellIntegration, TerminalLocation, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
1818
import { ITerminalFont, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal';
@@ -776,7 +776,10 @@ class AccessibleBuffer extends DisposableStore {
776776
private _accessibleBuffer: HTMLElement;
777777
private _bufferEditor: CodeEditorWidget;
778778
private _editorContainer: HTMLElement;
779+
private _commandFinishedDisposable: IDisposable | undefined;
780+
private _refreshSelection: boolean = true;
779781
private _registered: boolean = false;
782+
private _lastContentLength: number = 0;
780783
private _font: ITerminalFont;
781784

782785
constructor(
@@ -824,27 +827,45 @@ class AccessibleBuffer extends DisposableStore {
824827

825828
async focus(): Promise<void> {
826829
await this._updateBufferEditor();
827-
// Updates xterm's accessibleBufferActive property
828-
// such that mouse events do not cause the terminal buffer
829-
// to steal the focus
830-
this._accessibleBuffer.focus();
831-
this._bufferEditor.focus();
832830
}
833831

834832
private async _updateBufferEditor(): Promise<void> {
833+
const commandDetection = this._capabilities.get(TerminalCapability.CommandDetection);
834+
const fragment = !!commandDetection ? this._getShellIntegrationContent() : this._getAllContent();
835+
const model = await this._getTextModel(URI.from({ scheme: ACCESSIBLE_BUFFER.Scheme, fragment }));
836+
if (model) {
837+
this._bufferEditor.setModel(model);
838+
}
839+
835840
if (!this._registered) {
836-
// Registration is delayed until focus so the capability has time to have been added
837841
this.add(this._terminal.raw.registerBufferElementProvider({ provideBufferElements: () => this._editorContainer }));
842+
// When this is created, the element isn't yet attached so the dimensions are tiny
843+
this._bufferEditor.layout({ width: this._accessibleBuffer.clientWidth, height: this._accessibleBuffer.clientHeight });
838844
this._registered = true;
839845
}
840-
// When this is created, the element isn't yet attached so the dimensions are tiny
841-
this._bufferEditor.layout({ width: this._accessibleBuffer.clientWidth, height: this._accessibleBuffer.clientHeight });
842-
const commandDetection = this._capabilities.has(TerminalCapability.CommandDetection);
843-
const fragment = commandDetection ? this._getShellIntegrationContent() : this._getAllContent();
844-
const model = await this._getTextModel(URI.from({ scheme: ACCESSIBLE_BUFFER.Scheme, fragment }));
845-
if (model) {
846-
this._bufferEditor.setModel(model);
846+
847+
if (!this._commandFinishedDisposable && commandDetection) {
848+
this._commandFinishedDisposable = commandDetection.onCommandFinished(() => this._refreshSelection = true);
849+
this.add(this._commandFinishedDisposable);
850+
}
851+
852+
if (this._lastContentLength !== fragment.length || this._refreshSelection) {
853+
let lineNumber = 1;
854+
const lineCount = model?.getLineCount();
855+
if (lineCount && model) {
856+
lineNumber = commandDetection ? lineCount - 1 : lineCount > 2 ? lineCount - 2 : 1;
857+
}
858+
this._bufferEditor.setSelection({ startLineNumber: lineNumber, startColumn: 1, endLineNumber: lineNumber, endColumn: 1 });
859+
this._bufferEditor.setScrollTop(this._bufferEditor.getScrollHeight());
860+
this._refreshSelection = false;
861+
this._lastContentLength = fragment.length;
847862
}
863+
864+
// Updates xterm's accessibleBufferActive property
865+
// such that mouse events do not cause the terminal buffer
866+
// to steal the focus
867+
this._accessibleBuffer.focus();
868+
this._bufferEditor.focus();
848869
}
849870

850871
async _getTextModel(resource: URI): Promise<ITextModel | null> {
@@ -887,7 +908,7 @@ class AccessibleBuffer extends DisposableStore {
887908
}
888909
const isWrapped = buffer.getLine(i + 1)?.isWrapped;
889910
currentLine += line.translateToString(!isWrapped);
890-
if (!isWrapped || i === end - 1) {
911+
if (currentLine && !isWrapped || i === end - 1) {
891912
lines.push(currentLine.replace(new RegExp(' ', 'g'), '\xA0'));
892913
currentLine = '';
893914
}

0 commit comments

Comments
 (0)