diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 3ac6a3945fc..282aa660ced 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -418,6 +418,12 @@ export interface ITerminalLaunchError { code?: number; } +export interface IProcessReadyEvent { + pid: number, + cwd: string, + requiresWindowsMode?: boolean +} + /** * An interface representing a raw terminal child process, this contains a subset of the * child_process.ChildProcess node.js interface. @@ -437,7 +443,7 @@ export interface ITerminalChildProcess { onProcessData: Event; onProcessExit: Event; - onProcessReady: Event<{ pid: number, cwd: string }>; + onProcessReady: Event; onProcessTitleChanged: Event; onProcessOverrideDimensions?: Event; onProcessResolvedShellLaunchConfig?: Event; diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index 6c636366f07..6951a9c4bc4 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -5,7 +5,7 @@ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { IProcessEnvironment, isWindows, OperatingSystem, OS } from 'vs/base/common/platform'; -import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, LocalReconnectConstants, ITerminalsLayoutInfo, IRawTerminalInstanceLayoutInfo, ITerminalTabLayoutInfoById, ITerminalInstanceLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, LocalReconnectConstants, ITerminalsLayoutInfo, IRawTerminalInstanceLayoutInfo, ITerminalTabLayoutInfoById, ITerminalInstanceLayoutInfoById, TerminalShellType, IProcessReadyEvent } from 'vs/platform/terminal/common/terminal'; import { AutoOpenBarrier, Queue, RunOnceScheduler } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder'; @@ -281,7 +281,7 @@ export class PersistentTerminalProcess extends Disposable { private readonly _onProcessReplay = this._register(new Emitter()); readonly onProcessReplay = this._onProcessReplay.event; - private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); + private readonly _onProcessReady = this._register(new Emitter()); readonly onProcessReady = this._onProcessReady.event; private readonly _onProcessTitleChanged = this._register(new Emitter()); readonly onProcessTitleChanged = this._onProcessTitleChanged.event; @@ -377,7 +377,7 @@ export class PersistentTerminalProcess extends Disposable { } this._isStarted = true; } else { - this._onProcessReady.fire({ pid: this._pid, cwd: this._cwd }); + this._onProcessReady.fire({ pid: this._pid, cwd: this._cwd, requiresWindowsMode: isWindows && getWindowsBuildNumber() <= 19041 }); this._onProcessTitleChanged.fire(this._terminalProcess.currentTitle); this._onProcessShellTypeChanged.fire(this._terminalProcess.shellType); this.triggerReplay(); diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index 1f6aa23f52c..4fca95085ee 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -9,7 +9,7 @@ import * as fs from 'fs'; import * as os from 'os'; import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IShellLaunchConfig, ITerminalLaunchError, FlowControlConstants, ITerminalChildProcess, ITerminalDimensionsOverride, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IShellLaunchConfig, ITerminalLaunchError, FlowControlConstants, ITerminalChildProcess, ITerminalDimensionsOverride, TerminalShellType, IProcessReadyEvent } from 'vs/platform/terminal/common/terminal'; import { exec } from 'child_process'; import { ILogService } from 'vs/platform/log/common/log'; import { findExecutable, getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; @@ -99,8 +99,8 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess get onProcessData(): Event { return this._onProcessData.event; } private readonly _onProcessExit = this._register(new Emitter()); get onProcessExit(): Event { return this._onProcessExit.event; } - private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); - get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } + private readonly _onProcessReady = this._register(new Emitter()); + get onProcessReady(): Event { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = this._register(new Emitter()); get onProcessTitleChanged(): Event { return this._onProcessTitleChanged.event; } private readonly _onProcessShellTypeChanged = this._register(new Emitter()); @@ -324,7 +324,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } private _sendProcessId(pid: number) { - this._onProcessReady.fire({ pid, cwd: this._initialCwd }); + this._onProcessReady.fire({ pid, cwd: this._initialCwd, requiresWindowsMode: isWindows && getWindowsBuildNumber() <= 19041 }); } private _sendProcessTitle(ptyProcess: pty.IPty): void { diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index 0520601bbf0..25b677b7041 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -18,7 +18,7 @@ import { serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/ter import { CancellationTokenSource } from 'vs/base/common/cancellation'; import { generateUuid } from 'vs/base/common/uuid'; import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, ITerminalProfile, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessReadyEvent, IShellLaunchConfigDto, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, ITerminalProfile, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, IDisposable { @@ -193,8 +193,8 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess { public readonly onProcessData: Event = this._onProcessData.event; private readonly _onProcessExit = new Emitter(); public readonly onProcessExit: Event = this._onProcessExit.event; - private readonly _onProcessReady = new Emitter<{ pid: number, cwd: string }>(); - public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } + private readonly _onProcessReady = new Emitter(); + public get onProcessReady(): Event { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = new Emitter(); public readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; private readonly _onProcessOverrideDimensions = new Emitter(); diff --git a/src/vs/workbench/contrib/terminal/browser/remotePty.ts b/src/vs/workbench/contrib/terminal/browser/remotePty.ts index defd36db3f2..29a1dcddd88 100644 --- a/src/vs/workbench/contrib/terminal/browser/remotePty.ts +++ b/src/vs/workbench/contrib/terminal/browser/remotePty.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { ILogService } from 'vs/platform/log/common/log'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; import { RemoteTerminalChannelClient } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; @@ -19,8 +19,8 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { readonly onProcessData: Event = this._onProcessData.event; private readonly _onProcessExit = this._register(new Emitter()); readonly onProcessExit: Event = this._onProcessExit.event; - readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); - get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } + readonly _onProcessReady = this._register(new Emitter()); + get onProcessReady(): Event { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = this._register(new Emitter()); readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; private readonly _onProcessShellTypeChanged = this._register(new Emitter()); @@ -124,7 +124,7 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { handleExit(e: number | undefined) { this._onProcessExit.fire(e); } - handleReady(e: { pid: number, cwd: string }) { + handleReady(e: IProcessReadyEvent) { this._onProcessReady.fire(e); } handleTitleChanged(e: string) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 1a0da124ab2..8591578a436 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -546,9 +546,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { }); // Init winpty compat and link handler after process creation as they rely on the // underlying process OS - this._processManager.onProcessReady(() => { + this._processManager.onProcessReady((processTraits) => { if (this._processManager.os === OperatingSystem.Windows) { - xterm.setOption('windowsMode', true); + xterm.setOption('windowsMode', processTraits.requiresWindowsMode || false); // Force line data to be sent when the cursor is moved, the main purpose for // this is because ConPTY will often not do a line feed but instead move the // cursor, in which case we still want to send the current line's data to tasks. diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts index 9e807659a6e..e191726ff13 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts @@ -5,7 +5,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; -import { IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; @@ -17,8 +17,8 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal readonly onProcessData: Event = this._onProcessData.event; private readonly _onProcessExit = this._register(new Emitter()); readonly onProcessExit: Event = this._onProcessExit.event; - private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); - get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } + private readonly _onProcessReady = this._register(new Emitter()); + get onProcessReady(): Event { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = this._register(new Emitter()); readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; private readonly _onProcessOverrideDimensions = this._register(new Emitter()); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index a4c6b6303f6..56058db612a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -22,7 +22,7 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { EnvironmentVariableInfoChangesActive, EnvironmentVariableInfoStale } from 'vs/workbench/contrib/terminal/browser/environmentVariableInfo'; import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { IEnvironmentVariableInfo, IEnvironmentVariableService, IMergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, FlowControlConstants, TerminalShellType, ILocalTerminalService, IOffProcessTerminalService, ITerminalDimensions, TerminalSettingId } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalEnvironment, ITerminalLaunchError, FlowControlConstants, TerminalShellType, ILocalTerminalService, IOffProcessTerminalService, ITerminalDimensions, TerminalSettingId, IProcessReadyEvent } from 'vs/platform/terminal/common/terminal'; import { TerminalRecorder } from 'vs/platform/terminal/common/terminalRecorder'; import { localize } from 'vs/nls'; import { formatMessageForTerminal } from 'vs/workbench/contrib/terminal/common/terminalStrings'; @@ -85,8 +85,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce private readonly _onPtyReconnect = this._register(new Emitter()); get onPtyReconnect(): Event { return this._onPtyReconnect.event; } - private readonly _onProcessReady = this._register(new Emitter()); - get onProcessReady(): Event { return this._onProcessReady.event; } + private readonly _onProcessReady = this._register(new Emitter()); + get onProcessReady(): Event { return this._onProcessReady.event; } private readonly _onProcessStateChange = this._register(new Emitter()); get onProcessStateChange(): Event { return this._onProcessStateChange.event; } private readonly _onBeforeProcessData = this._register(new Emitter()); @@ -201,7 +201,6 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce } else { this.remoteAuthority = this._workbenchEnvironmentService.remoteAuthority; } - const hasRemoteAuthority = !!this.remoteAuthority; // Create variable resolver const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(); @@ -212,7 +211,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce // they're connected to the remote. this.userHome = this._pathService.resolvedUserHome?.fsPath; this.os = OS; - if (hasRemoteAuthority) { + if (!!this.remoteAuthority) { const userHomeUri = await this._pathService.userHome(); this.userHome = userHomeUri.path; const remoteEnv = await this._remoteAgentService.getEnvironment(); @@ -299,10 +298,10 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce dispose(this._processListeners); } this._processListeners = [ - newProcess.onProcessReady((e: { pid: number, cwd: string }) => { + newProcess.onProcessReady((e: IProcessReadyEvent) => { this.shellProcessId = e.pid; this._initialCwd = e.cwd; - this._onProcessReady.fire(); + this._onProcessReady.fire(e); if (this._preLaunchInputQueue.length > 0 && this._process) { // Send any queued data that's waiting diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index 8652acfb70f..3c9c2b9e797 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -93,8 +93,8 @@ export class RemoteTerminalChannelClient { get onProcessExit(): Event<{ id: number, event: number | undefined }> { return this._channel.listen<{ id: number, event: number | undefined }>('$onProcessExitEvent'); } - get onProcessReady(): Event<{ id: number, event: { pid: number, cwd: string } }> { - return this._channel.listen<{ id: number, event: { pid: number, cwd: string } }>('$onProcessReadyEvent'); + get onProcessReady(): Event<{ id: number, event: { pid: number, cwd: string, requireWindowsMode?: boolean } }> { + return this._channel.listen<{ id: number, event: { pid: number, cwd: string, requiresWindowsMode?: boolean } }>('$onProcessReadyEvent'); } get onProcessReplay(): Event<{ id: number, event: IPtyHostProcessReplayEvent }> { return this._channel.listen<{ id: number, event: IPtyHostProcessReplayEvent }>('$onProcessReplayEvent'); diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 036d751afa6..2db99f8b269 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -9,7 +9,7 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import { RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform'; import { IExtensionPointDescriptor } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalDimensions, ITerminalDimensionsOverride, ITerminalLaunchError, ITerminalProfile, ITerminalProfileObject, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IEnvironmentVariableInfo } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -283,7 +283,7 @@ export interface ITerminalProcessManager extends IDisposable { readonly onPtyDisconnect: Event; readonly onPtyReconnect: Event; - readonly onProcessReady: Event; + readonly onProcessReady: Event; readonly onBeforeProcessData: Event; readonly onProcessData: Event; readonly onProcessTitle: Event; diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts index d136eb48052..529d9294fa3 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts @@ -6,7 +6,7 @@ import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal'; -import { IProcessDataEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; +import { IProcessDataEvent, IProcessReadyEvent, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensionsOverride, ITerminalLaunchError, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/terminalProcess'; /** @@ -22,7 +22,7 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { readonly onProcessReplay = this._onProcessReplay.event; private readonly _onProcessExit = this._register(new Emitter()); readonly onProcessExit = this._onProcessExit.event; - private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); + private readonly _onProcessReady = this._register(new Emitter()); readonly onProcessReady = this._onProcessReady.event; private readonly _onProcessTitleChanged = this._register(new Emitter()); readonly onProcessTitleChanged = this._onProcessTitleChanged.event; @@ -91,7 +91,7 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { handleExit(e: number | undefined) { this._onProcessExit.fire(e); } - handleReady(e: { pid: number, cwd: string }) { + handleReady(e: IProcessReadyEvent) { this._onProcessReady.fire(e); } handleTitleChanged(e: string) {