mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-22 21:00:30 -04:00
Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)
* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 * disable strict null check
This commit is contained in:
@@ -25,23 +25,24 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB
|
||||
import { ICssStyleCollector, ITheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
|
||||
import { PANEL_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/terminalWidgetManager';
|
||||
import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_PANEL_ID, IWindowsShellHelper, SHELL_PATH_INVALID_EXIT_CODE } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IShellLaunchConfig, ITerminalDimensions, ITerminalInstance, ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_PANEL_ID, IWindowsShellHelper, SHELL_PATH_INVALID_EXIT_CODE, SHELL_PATH_DIRECTORY_EXIT_CODE, SHELL_CWD_INVALID_EXIT_CODE } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
|
||||
import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminalCommands';
|
||||
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
|
||||
import { TerminalLinkHandler } from 'vs/workbench/contrib/terminal/browser/terminalLinkHandler';
|
||||
import { TerminalCommandTracker } from 'vs/workbench/contrib/terminal/browser/terminalCommandTracker';
|
||||
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
||||
import { ISearchOptions, Terminal as XTermTerminal, IBuffer } from 'vscode-xterm';
|
||||
import { IAccessibilityService, AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility';
|
||||
import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager';
|
||||
import { Terminal as XTermTerminal, IBuffer } from 'xterm';
|
||||
import { SearchAddon, ISearchOptions } from 'xterm-addon-search';
|
||||
|
||||
// How long in milliseconds should an average frame take to render for a notification to appear
|
||||
// which suggests the fallback DOM-based renderer
|
||||
const SLOW_CANVAS_RENDER_THRESHOLD = 50;
|
||||
const NUMBER_OF_FRAMES_TO_MEASURE = 20;
|
||||
|
||||
|
||||
export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [
|
||||
TERMINAL_COMMAND_ID.CLEAR_SELECTION,
|
||||
TERMINAL_COMMAND_ID.CLEAR,
|
||||
@@ -148,10 +149,23 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [
|
||||
'workbench.action.toggleMaximizedPanel'
|
||||
];
|
||||
|
||||
let xtermConstructor: Promise<typeof XTermTerminal> | undefined;
|
||||
|
||||
interface ICanvasDimensions {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
interface IGridDimensions {
|
||||
cols: number;
|
||||
rows: number;
|
||||
}
|
||||
|
||||
export class TerminalInstance implements ITerminalInstance {
|
||||
private static readonly EOL_REGEX = /\r?\n/g;
|
||||
|
||||
private static _lastKnownDimensions: dom.Dimension | null = null;
|
||||
private static _lastKnownCanvasDimensions: ICanvasDimensions | undefined;
|
||||
private static _lastKnownGridDimensions: IGridDimensions | undefined;
|
||||
private static _idCounter = 1;
|
||||
|
||||
private _processManager: ITerminalProcessManager | undefined;
|
||||
@@ -166,17 +180,18 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
private _title: string;
|
||||
private _wrapperElement: HTMLDivElement;
|
||||
private _xterm: XTermTerminal;
|
||||
private _xtermSearch: SearchAddon | undefined;
|
||||
private _xtermElement: HTMLDivElement;
|
||||
private _terminalHasTextContextKey: IContextKey<boolean>;
|
||||
private _cols: number;
|
||||
private _rows: number;
|
||||
private _dimensionsOverride: ITerminalDimensions;
|
||||
private _dimensionsOverride: ITerminalDimensions | undefined;
|
||||
private _windowsShellHelper: IWindowsShellHelper | undefined;
|
||||
private _xtermReadyPromise: Promise<void>;
|
||||
private _titleReadyPromise: Promise<string>;
|
||||
private _titleReadyComplete: (title: string) => any;
|
||||
|
||||
private _disposables: lifecycle.IDisposable[];
|
||||
private readonly _disposables = new lifecycle.DisposableStore();
|
||||
private _messageTitleDisposable: lifecycle.IDisposable | undefined;
|
||||
|
||||
private _widgetManager: TerminalWidgetManager;
|
||||
@@ -197,6 +212,8 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}
|
||||
return this._rows;
|
||||
}
|
||||
public get maxCols(): number { return this._cols; }
|
||||
public get maxRows(): number { return this._rows; }
|
||||
// TODO: Ideally processId would be merged into processReady
|
||||
public get processId(): number | undefined { return this._processManager ? this._processManager.shellProcessId : undefined; }
|
||||
// TODO: How does this work with detached processes?
|
||||
@@ -228,6 +245,8 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
public get onRequestExtHostProcess(): Event<ITerminalInstance> { return this._onRequestExtHostProcess.event; }
|
||||
private readonly _onDimensionsChanged = new Emitter<void>();
|
||||
public get onDimensionsChanged(): Event<void> { return this._onDimensionsChanged.event; }
|
||||
private readonly _onMaximumDimensionsChanged = new Emitter<void>();
|
||||
public get onMaximumDimensionsChanged(): Event<void> { return this._onMaximumDimensionsChanged.event; }
|
||||
private readonly _onFocus = new Emitter<ITerminalInstance>();
|
||||
public get onFocus(): Event<ITerminalInstance> { return this._onFocus.event; }
|
||||
|
||||
@@ -249,7 +268,6 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
@IStorageService private readonly _storageService: IStorageService,
|
||||
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService
|
||||
) {
|
||||
this._disposables = [];
|
||||
this._skipTerminalCommands = [];
|
||||
this._isExiting = false;
|
||||
this._hadFocusOnExit = false;
|
||||
@@ -296,7 +314,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}
|
||||
|
||||
public addDisposable(disposable: lifecycle.IDisposable): void {
|
||||
this._disposables.push(disposable);
|
||||
this._disposables.add(disposable);
|
||||
}
|
||||
|
||||
private _initDimensions(): void {
|
||||
@@ -320,16 +338,19 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
private _evaluateColsAndRows(width: number, height: number): number | null {
|
||||
// Ignore if dimensions are undefined or 0
|
||||
if (!width || !height) {
|
||||
this._setLastKnownColsAndRows();
|
||||
return null;
|
||||
}
|
||||
|
||||
const dimension = this._getDimension(width, height);
|
||||
if (!dimension) {
|
||||
this._setLastKnownColsAndRows();
|
||||
return null;
|
||||
}
|
||||
|
||||
const font = this._configHelper.getFont(this._xterm);
|
||||
if (!font.charWidth || !font.charHeight) {
|
||||
this._setLastKnownColsAndRows();
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -345,26 +366,44 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
} else {
|
||||
scaledCharWidth = Math.floor(font.charWidth * window.devicePixelRatio) + font.letterSpacing;
|
||||
}
|
||||
this._cols = Math.max(Math.floor(scaledWidthAvailable / scaledCharWidth), 1);
|
||||
const newCols = Math.max(Math.floor(scaledWidthAvailable / scaledCharWidth), 1);
|
||||
|
||||
const scaledHeightAvailable = dimension.height * window.devicePixelRatio;
|
||||
const scaledCharHeight = Math.ceil(font.charHeight * window.devicePixelRatio);
|
||||
const scaledLineHeight = Math.floor(scaledCharHeight * font.lineHeight);
|
||||
this._rows = Math.max(Math.floor(scaledHeightAvailable / scaledLineHeight), 1);
|
||||
const newRows = Math.max(Math.floor(scaledHeightAvailable / scaledLineHeight), 1);
|
||||
|
||||
if (this._cols !== newCols || this._rows !== newRows) {
|
||||
this._cols = newCols;
|
||||
this._rows = newRows;
|
||||
this._fireMaximumDimensionsChanged();
|
||||
}
|
||||
|
||||
return dimension.width;
|
||||
}
|
||||
|
||||
private _getDimension(width: number, height: number): dom.Dimension | null {
|
||||
private _setLastKnownColsAndRows(): void {
|
||||
if (TerminalInstance._lastKnownGridDimensions) {
|
||||
this._cols = TerminalInstance._lastKnownGridDimensions.cols;
|
||||
this._rows = TerminalInstance._lastKnownGridDimensions.rows;
|
||||
}
|
||||
}
|
||||
|
||||
@debounce(50)
|
||||
private _fireMaximumDimensionsChanged(): void {
|
||||
this._onMaximumDimensionsChanged.fire();
|
||||
}
|
||||
|
||||
private _getDimension(width: number, height: number): ICanvasDimensions | undefined {
|
||||
// The font needs to have been initialized
|
||||
const font = this._configHelper.getFont(this._xterm);
|
||||
if (!font || !font.charWidth || !font.charHeight) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// The panel is minimized
|
||||
if (!this._isVisible) {
|
||||
return TerminalInstance._lastKnownDimensions;
|
||||
return TerminalInstance._lastKnownCanvasDimensions;
|
||||
} else {
|
||||
// Trigger scroll event manually so that the viewport's scroll area is synced. This
|
||||
// needs to happen otherwise its scrollTop value is invalid when the panel is toggled as
|
||||
@@ -376,7 +415,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}
|
||||
|
||||
if (!this._wrapperElement) {
|
||||
return null;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const wrapperElementStyle = getComputedStyle(this._wrapperElement);
|
||||
@@ -387,15 +426,29 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
const innerWidth = width - marginLeft - marginRight;
|
||||
const innerHeight = height - bottom;
|
||||
|
||||
TerminalInstance._lastKnownDimensions = new dom.Dimension(innerWidth, innerHeight);
|
||||
return TerminalInstance._lastKnownDimensions;
|
||||
TerminalInstance._lastKnownCanvasDimensions = new dom.Dimension(innerWidth, innerHeight);
|
||||
return TerminalInstance._lastKnownCanvasDimensions;
|
||||
}
|
||||
|
||||
private async _getXtermConstructor(): Promise<typeof XTermTerminal> {
|
||||
if (xtermConstructor) {
|
||||
return xtermConstructor;
|
||||
}
|
||||
xtermConstructor = new Promise<typeof XTermTerminal>(async (resolve) => {
|
||||
const Terminal = await this._terminalInstanceService.getXtermConstructor();
|
||||
// Localize strings
|
||||
Terminal.strings.promptLabel = nls.localize('terminal.integrated.a11yPromptLabel', 'Terminal input');
|
||||
Terminal.strings.tooMuchOutput = nls.localize('terminal.integrated.a11yTooMuchOutput', 'Too much output to announce, navigate to rows manually to read');
|
||||
resolve(Terminal);
|
||||
});
|
||||
return xtermConstructor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create xterm.js instance and attach data listeners.
|
||||
*/
|
||||
protected async _createXterm(): Promise<void> {
|
||||
const Terminal = await this._terminalInstanceService.getXtermConstructor();
|
||||
const Terminal = await this._getXtermConstructor();
|
||||
const font = this._configHelper.getFont(undefined, true);
|
||||
const config = this._configHelper.config;
|
||||
this._xterm = new Terminal({
|
||||
@@ -414,9 +467,11 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
macOptionClickForcesSelection: config.macOptionClickForcesSelection,
|
||||
rightClickSelectsWord: config.rightClickBehavior === 'selectWord',
|
||||
// TODO: Guess whether to use canvas or dom better
|
||||
rendererType: config.rendererType === 'auto' ? 'canvas' : config.rendererType,
|
||||
// TODO: Remove this once the setting is removed upstream
|
||||
experimentalCharAtlas: 'dynamic'
|
||||
rendererType: config.rendererType === 'auto' ? 'canvas' : config.rendererType
|
||||
});
|
||||
this._terminalInstanceService.getXtermSearchConstructor().then(Addon => {
|
||||
this._xtermSearch = new Addon();
|
||||
this._xterm.loadAddon(this._xtermSearch);
|
||||
});
|
||||
if (this._shellLaunchConfig.initialText) {
|
||||
this._xterm.writeln(this._shellLaunchConfig.initialText);
|
||||
@@ -447,10 +502,10 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, platform.platform, this._processManager);
|
||||
this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, this._processManager);
|
||||
});
|
||||
} else if (this.shellLaunchConfig.isRendererOnly) {
|
||||
this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, undefined, undefined);
|
||||
this._linkHandler = this._instantiationService.createInstance(TerminalLinkHandler, this._xterm, undefined);
|
||||
}
|
||||
|
||||
// Register listener to trigger the onInput ext API if the terminal is a renderer only
|
||||
@@ -459,7 +514,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}
|
||||
|
||||
this._commandTracker = new TerminalCommandTracker(this._xterm);
|
||||
this._disposables.push(this._themeService.onThemeChange(theme => this._updateTheme(theme)));
|
||||
this._disposables.add(this._themeService.onThemeChange(theme => this._updateTheme(theme)));
|
||||
}
|
||||
|
||||
private _isScreenReaderOptimized(): boolean {
|
||||
@@ -541,7 +596,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
|
||||
return true;
|
||||
});
|
||||
this._disposables.push(dom.addDisposableListener(this._xterm.element, 'mousedown', () => {
|
||||
this._disposables.add(dom.addDisposableListener(this._xterm.element, 'mousedown', () => {
|
||||
// We need to listen to the mouseup event on the document since the user may release
|
||||
// the mouse button anywhere outside of _xterm.element.
|
||||
const listener = dom.addDisposableListener(document, 'mouseup', () => {
|
||||
@@ -553,7 +608,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}));
|
||||
|
||||
// xterm.js currently drops selection on keyup as we need to handle this case.
|
||||
this._disposables.push(dom.addDisposableListener(this._xterm.element, 'keyup', () => {
|
||||
this._disposables.add(dom.addDisposableListener(this._xterm.element, 'keyup', () => {
|
||||
// Wait until keyup has propagated through the DOM before evaluating
|
||||
// the new selection state.
|
||||
setTimeout(() => this._refreshSelectionContextKey(), 0);
|
||||
@@ -563,7 +618,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
const focusTrap: HTMLElement = document.createElement('div');
|
||||
focusTrap.setAttribute('tabindex', '0');
|
||||
dom.addClass(focusTrap, 'focus-trap');
|
||||
this._disposables.push(dom.addDisposableListener(focusTrap, 'focus', () => {
|
||||
this._disposables.add(dom.addDisposableListener(focusTrap, 'focus', () => {
|
||||
let currentElement = focusTrap;
|
||||
while (!dom.hasClass(currentElement, 'part')) {
|
||||
currentElement = currentElement.parentElement!;
|
||||
@@ -573,18 +628,18 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}));
|
||||
xtermHelper.insertBefore(focusTrap, this._xterm.textarea);
|
||||
|
||||
this._disposables.push(dom.addDisposableListener(this._xterm.textarea, 'focus', () => {
|
||||
this._disposables.add(dom.addDisposableListener(this._xterm.textarea, 'focus', () => {
|
||||
this._terminalFocusContextKey.set(true);
|
||||
this._onFocused.fire(this);
|
||||
}));
|
||||
this._disposables.push(dom.addDisposableListener(this._xterm.textarea, 'blur', () => {
|
||||
this._disposables.add(dom.addDisposableListener(this._xterm.textarea, 'blur', () => {
|
||||
this._terminalFocusContextKey.reset();
|
||||
this._refreshSelectionContextKey();
|
||||
}));
|
||||
this._disposables.push(dom.addDisposableListener(this._xterm.element, 'focus', () => {
|
||||
this._disposables.add(dom.addDisposableListener(this._xterm.element, 'focus', () => {
|
||||
this._terminalFocusContextKey.set(true);
|
||||
}));
|
||||
this._disposables.push(dom.addDisposableListener(this._xterm.element, 'blur', () => {
|
||||
this._disposables.add(dom.addDisposableListener(this._xterm.element, 'blur', () => {
|
||||
this._terminalFocusContextKey.reset();
|
||||
this._refreshSelectionContextKey();
|
||||
}));
|
||||
@@ -595,19 +650,6 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
if (this._processManager) {
|
||||
this._widgetManager = new TerminalWidgetManager(this._wrapperElement);
|
||||
this._processManager.onProcessReady(() => this._linkHandler.setWidgetManager(this._widgetManager));
|
||||
|
||||
this._processManager.onProcessReady(() => {
|
||||
if (this._configHelper.config.enableLatencyMitigation) {
|
||||
if (!this._processManager) {
|
||||
return;
|
||||
}
|
||||
this._processManager.getLatency().then(latency => {
|
||||
if (latency > 20 && (this._xterm as any).typeAheadInit) {
|
||||
(this._xterm as any).typeAheadInit(this._processManager, this._themeService);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (this._shellLaunchConfig.isRendererOnly) {
|
||||
this._widgetManager = new TerminalWidgetManager(this._wrapperElement);
|
||||
this._linkHandler.setWidgetManager(this._widgetManager);
|
||||
@@ -635,7 +677,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
|
||||
private _measureRenderTime(): void {
|
||||
const frameTimes: number[] = [];
|
||||
const textRenderLayer = this._xterm._core._renderCoordinator._renderer._renderLayers[0];
|
||||
const textRenderLayer = this._xterm._core._renderService._renderer._renderLayers[0];
|
||||
const originalOnGridChanged = textRenderLayer.onGridChanged;
|
||||
|
||||
const evaluateCanvasRenderer = () => {
|
||||
@@ -691,9 +733,9 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
return this._xterm && this._xterm.hasSelection();
|
||||
}
|
||||
|
||||
public copySelection(): void {
|
||||
public async copySelection(): Promise<void> {
|
||||
if (this.hasSelection()) {
|
||||
this._clipboardService.writeText(this._xterm.getSelection());
|
||||
await this._clipboardService.writeText(this._xterm.getSelection());
|
||||
} else {
|
||||
this._notificationService.warn(nls.localize('terminal.integrated.copySelection.noSelection', 'The terminal has no selection to copy'));
|
||||
}
|
||||
@@ -714,11 +756,17 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}
|
||||
|
||||
public findNext(term: string, searchOptions: ISearchOptions): boolean {
|
||||
return this._xterm.findNext(term, searchOptions);
|
||||
if (!this._xtermSearch) {
|
||||
return false;
|
||||
}
|
||||
return this._xtermSearch.findNext(term, searchOptions);
|
||||
}
|
||||
|
||||
public findPrevious(term: string, searchOptions: ISearchOptions): boolean {
|
||||
return this._xterm.findPrevious(term, searchOptions);
|
||||
if (!this._xtermSearch) {
|
||||
return false;
|
||||
}
|
||||
return this._xtermSearch.findPrevious(term, searchOptions);
|
||||
}
|
||||
|
||||
public notifyFindWidgetFocusChanged(isFocused: boolean): void {
|
||||
@@ -770,12 +818,12 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
this._isDisposed = true;
|
||||
this._onDisposed.fire(this);
|
||||
}
|
||||
this._disposables = lifecycle.dispose(this._disposables);
|
||||
this._disposables.dispose();
|
||||
}
|
||||
|
||||
public rendererExit(exitCode: number): void {
|
||||
// The use of this API is for cases where there is no backing process behind a terminal
|
||||
// instance (eg. a custom execution task).
|
||||
// instance (e.g. a custom execution task).
|
||||
if (!this.shellLaunchConfig.isRendererOnly) {
|
||||
throw new Error('rendererExit is only expected to be called on a renderer only terminal');
|
||||
}
|
||||
@@ -915,10 +963,11 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}
|
||||
|
||||
protected _createProcess(): void {
|
||||
this._processManager = this._terminalInstanceService.createTerminalProcessManager(this._id, this._configHelper);
|
||||
this._processManager = this._instantiationService.createInstance(TerminalProcessManager, this._id, this._configHelper);
|
||||
this._processManager.onProcessReady(() => this._onProcessIdReady.fire(this));
|
||||
this._processManager.onProcessExit(exitCode => this._onProcessExit(exitCode));
|
||||
this._processManager.onProcessData(data => this._onData.fire(data));
|
||||
this._processManager.onProcessOverrideDimensions(e => this.setDimensions(e));
|
||||
|
||||
if (this._shellLaunchConfig.name) {
|
||||
this.setTitle(this._shellLaunchConfig.name, false);
|
||||
@@ -944,7 +993,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
// Create the process asynchronously to allow the terminal's container
|
||||
// to be created so dimensions are accurate
|
||||
setTimeout(() => {
|
||||
this._processManager!.createProcess(this._shellLaunchConfig, this._cols, this._rows);
|
||||
this._processManager!.createProcess(this._shellLaunchConfig, this._cols, this._rows, this._isScreenReaderOptimized());
|
||||
}, 0);
|
||||
}
|
||||
|
||||
@@ -959,7 +1008,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
|
||||
/**
|
||||
* Called when either a process tied to a terminal has exited or when a terminal renderer
|
||||
* simulates a process exiting (eg. custom execution task).
|
||||
* simulates a process exiting (e.g. custom execution task).
|
||||
* @param exitCode The exit code of the process, this is undefined when the terminal was exited
|
||||
* through user action.
|
||||
*/
|
||||
@@ -977,7 +1026,11 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
// Create exit code message
|
||||
if (exitCode) {
|
||||
if (exitCode === SHELL_PATH_INVALID_EXIT_CODE) {
|
||||
exitCodeMessage = nls.localize('terminal.integrated.exitedWithInvalidPath', 'The terminal shell path does not exist: {0}', this._shellLaunchConfig.executable);
|
||||
exitCodeMessage = nls.localize('terminal.integrated.exitedWithInvalidPath', 'The terminal shell path "{0}" does not exist', this._shellLaunchConfig.executable);
|
||||
} else if (exitCode === SHELL_PATH_DIRECTORY_EXIT_CODE) {
|
||||
exitCodeMessage = nls.localize('terminal.integrated.exitedWithInvalidPathDirectory', 'The terminal shell path "{0}" is a directory', this._shellLaunchConfig.executable);
|
||||
} else if (exitCode === SHELL_CWD_INVALID_EXIT_CODE && this._shellLaunchConfig.cwd) {
|
||||
exitCodeMessage = nls.localize('terminal.integrated.exitedWithInvalidCWD', 'The terminal shell CWD "{0}" does not exist', this._shellLaunchConfig.cwd.toString());
|
||||
} else if (this._processManager && this._processManager.processState === ProcessState.KILLED_DURING_LAUNCH) {
|
||||
let args = '';
|
||||
if (typeof this._shellLaunchConfig.args === 'string') {
|
||||
@@ -1123,9 +1176,17 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
}
|
||||
|
||||
private _sendLineData(buffer: IBuffer, lineIndex: number): void {
|
||||
let lineData = buffer.getLine(lineIndex)!.translateToString(true);
|
||||
while (lineIndex >= 0 && buffer.getLine(lineIndex--)!.isWrapped) {
|
||||
lineData = buffer.getLine(lineIndex)!.translateToString(false) + lineData;
|
||||
let line = buffer.getLine(lineIndex);
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
let lineData = line.translateToString(true);
|
||||
while (lineIndex > 0 && line.isWrapped) {
|
||||
line = buffer.getLine(--lineIndex);
|
||||
if (!line) {
|
||||
break;
|
||||
}
|
||||
lineData = line.translateToString(false) + lineData;
|
||||
}
|
||||
this._onLineData.fire(lineData);
|
||||
}
|
||||
@@ -1216,7 +1277,6 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const terminalWidth = this._evaluateColsAndRows(dimension.width, dimension.height);
|
||||
if (!terminalWidth) {
|
||||
return;
|
||||
@@ -1249,18 +1309,24 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
this._safeSetOption('drawBoldTextInBrightColors', config.drawBoldTextInBrightColors);
|
||||
}
|
||||
|
||||
if (isNaN(cols) || isNaN(rows)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cols !== this._xterm.cols || rows !== this._xterm.rows) {
|
||||
this._onDimensionsChanged.fire();
|
||||
}
|
||||
|
||||
this._xterm.resize(cols, rows);
|
||||
TerminalInstance._lastKnownGridDimensions = { cols, rows };
|
||||
|
||||
if (this._isVisible) {
|
||||
// HACK: Force the renderer to unpause by simulating an IntersectionObserver event.
|
||||
// This is to fix an issue where dragging the window to the top of the screen to
|
||||
// maximize on Windows/Linux would fire an event saying that the terminal was not
|
||||
// visible.
|
||||
if (this._xterm.getOption('rendererType') === 'canvas') {
|
||||
this._xterm._core._renderCoordinator._onIntersectionChange({ intersectionRatio: 1 });
|
||||
this._xterm._core._renderService._onIntersectionChange({ intersectionRatio: 1 });
|
||||
// HACK: Force a refresh of the screen to ensure links are refresh corrected.
|
||||
// This can probably be removed when the above hack is fixed in Chromium.
|
||||
this._xterm.refresh(0, this._xterm.rows - 1);
|
||||
@@ -1308,7 +1374,7 @@ export class TerminalInstance implements ITerminalInstance {
|
||||
return this._titleReadyPromise;
|
||||
}
|
||||
|
||||
public setDimensions(dimensions: ITerminalDimensions): void {
|
||||
public setDimensions(dimensions: ITerminalDimensions | undefined): void {
|
||||
this._dimensionsOverride = dimensions;
|
||||
this._resize();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user