mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-01 05:02:35 +01:00
@@ -680,6 +680,7 @@ export interface ITerminalChildProcess {
|
||||
|
||||
onProcessData: Event<IProcessDataEvent | string>;
|
||||
onProcessReady: Event<IProcessReadyEvent>;
|
||||
onProcessReplayComplete?: Event<void>;
|
||||
onDidChangeProperty: Event<IProcessProperty<any>>;
|
||||
onProcessExit: Event<number | undefined>;
|
||||
onRestoreCommands?: Event<ISerializedCommandDetectionCapability>;
|
||||
|
||||
@@ -536,6 +536,7 @@ export interface ITerminalInstance {
|
||||
onDisposed: Event<ITerminalInstance>;
|
||||
|
||||
onProcessIdReady: Event<ITerminalInstance>;
|
||||
onProcessReplayComplete: Event<void>;
|
||||
onRequestExtHostProcess: Event<ITerminalInstance>;
|
||||
onDimensionsChanged: Event<void>;
|
||||
onMaximumDimensionsChanged: Event<void>;
|
||||
|
||||
@@ -288,6 +288,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
readonly onDisposed = this._onDisposed.event;
|
||||
private readonly _onProcessIdReady = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onProcessIdReady = this._onProcessIdReady.event;
|
||||
private readonly _onProcessReplayComplete = this._register(new Emitter<void>());
|
||||
readonly onProcessReplayComplete = this._onProcessReplayComplete.event;
|
||||
private readonly _onTitleChanged = this._register(new Emitter<ITerminalInstance>());
|
||||
readonly onTitleChanged = this._onTitleChanged.event;
|
||||
private readonly _onIconChanged = this._register(new Emitter<{ instance: ITerminalInstance; userInitiated: boolean }>());
|
||||
@@ -1395,6 +1397,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance {
|
||||
this._initialDataEvents?.push(ev.data);
|
||||
this._onData.fire(ev.data);
|
||||
});
|
||||
processManager.onProcessReplayComplete(() => this._onProcessReplayComplete.fire());
|
||||
processManager.onEnvironmentVariableInfoChanged(e => this._onEnvironmentVariableInfoChanged(e));
|
||||
processManager.onPtyDisconnect(() => {
|
||||
if (this.xterm) {
|
||||
|
||||
@@ -108,6 +108,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
readonly onBeforeProcessData = this._onBeforeProcessData.event;
|
||||
private readonly _onProcessData = this._register(new Emitter<IProcessDataEvent>());
|
||||
readonly onProcessData = this._onProcessData.event;
|
||||
private readonly _onProcessReplayComplete = this._register(new Emitter<void>());
|
||||
readonly onProcessReplayComplete = this._onProcessReplayComplete.event;
|
||||
private readonly _onDidChangeProperty = this._register(new Emitter<IProcessProperty<any>>());
|
||||
readonly onDidChangeProperty = this._onDidChangeProperty.event;
|
||||
private readonly _onEnvironmentVariableInfoChange = this._register(new Emitter<IEnvironmentVariableInfo>());
|
||||
@@ -375,10 +377,11 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce
|
||||
this._onDidChangeProperty.fire({ type, value });
|
||||
})
|
||||
];
|
||||
if (newProcess.onProcessReplayComplete) {
|
||||
this._processListeners.push(newProcess.onProcessReplayComplete(() => this._onProcessReplayComplete.fire()));
|
||||
}
|
||||
if (newProcess.onRestoreCommands) {
|
||||
this._processListeners.push(newProcess.onRestoreCommands(e => {
|
||||
this._onRestoreCommands.fire(e);
|
||||
}));
|
||||
this._processListeners.push(newProcess.onRestoreCommands(e => this._onRestoreCommands.fire(e)));
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (this.processState === ProcessState.Launching) {
|
||||
|
||||
@@ -95,6 +95,8 @@ export class TerminalService implements ITerminalService {
|
||||
return this._detachedXterms;
|
||||
}
|
||||
|
||||
private _reconnectedTerminalGroups: Promise<ITerminalGroup[]> | undefined;
|
||||
|
||||
private _reconnectedTerminals: Map<string, ITerminalInstance[]> = new Map();
|
||||
getReconnectedTerminals(reconnectionOwner: string): ITerminalInstance[] | undefined {
|
||||
return this._reconnectedTerminals.get(reconnectionOwner);
|
||||
@@ -292,6 +294,13 @@ export class TerminalService implements ITerminalService {
|
||||
reconnectedPromise.then(async () => {
|
||||
this._setConnected();
|
||||
mark('code/terminal/didReconnect');
|
||||
mark('code/terminal/willReplay');
|
||||
const instances = await this._reconnectedTerminalGroups?.then(groups => groups.map(e => e.terminalInstances).flat()) ?? [];
|
||||
await Promise.all(instances.map(e => new Promise<void>(r => Event.once(e.onProcessReplayComplete)(() => {
|
||||
mark(`code/terminal/replay/${e.shellLaunchConfig.attachPersistentProcess?.id}`);
|
||||
r();
|
||||
}))));
|
||||
mark('code/terminal/didReplay');
|
||||
for (const backend of this._terminalInstanceService.getRegisteredBackends()) {
|
||||
mark('code/terminal/willGetPerformanceMarks');
|
||||
this._timerService.setPerformanceMarks(backend.remoteAuthority === undefined ? 'localPtyHost' : 'remotePtyHost', await backend.getPerformanceMarks());
|
||||
@@ -450,7 +459,7 @@ export class TerminalService implements ITerminalService {
|
||||
mark('code/terminal/didGetTerminalLayoutInfo');
|
||||
if (layoutInfo && layoutInfo.tabs.length > 0) {
|
||||
mark('code/terminal/willRecreateTerminalGroups');
|
||||
this._restoredGroupCount = await this._recreateTerminalGroups(layoutInfo);
|
||||
this._reconnectedTerminalGroups = this._recreateTerminalGroups(layoutInfo);
|
||||
mark('code/terminal/didRecreateTerminalGroups');
|
||||
}
|
||||
// now that terminals have been restored,
|
||||
@@ -458,17 +467,17 @@ export class TerminalService implements ITerminalService {
|
||||
this._attachProcessLayoutListeners();
|
||||
}
|
||||
|
||||
private async _recreateTerminalGroups(layoutInfo?: ITerminalsLayoutInfo): Promise<number> {
|
||||
private _recreateTerminalGroups(layoutInfo?: ITerminalsLayoutInfo): Promise<ITerminalGroup[]> {
|
||||
const groupPromises: Promise<ITerminalGroup | undefined>[] = [];
|
||||
let reconnectCounter = 0;
|
||||
let activeGroup: Promise<ITerminalGroup | undefined> | undefined;
|
||||
if (layoutInfo) {
|
||||
const tabPromises: Promise<ITerminalGroup | undefined>[] = [];
|
||||
for (const tabLayout of layoutInfo.tabs) {
|
||||
const terminalLayouts = tabLayout.terminals.filter(t => t.terminal && t.terminal.isOrphan);
|
||||
if (terminalLayouts.length) {
|
||||
reconnectCounter += terminalLayouts.length;
|
||||
const promise = this._recreateTerminalGroup(tabLayout, terminalLayouts);
|
||||
tabPromises.push(promise);
|
||||
groupPromises.push(promise);
|
||||
if (tabLayout.isActive) {
|
||||
activeGroup = promise;
|
||||
}
|
||||
@@ -482,7 +491,7 @@ export class TerminalService implements ITerminalService {
|
||||
activeGroup?.then(group => this._terminalGroupService.activeGroup = group);
|
||||
}
|
||||
}
|
||||
return reconnectCounter;
|
||||
return Promise.all(groupPromises).then(result => result.filter(e => !!e) as ITerminalGroup[]);
|
||||
}
|
||||
|
||||
private async _recreateTerminalGroup(tabLayout: IRawTerminalTabLayoutInfo<IPtyHostAttachTarget | null>, terminalLayouts: IRawTerminalInstanceLayoutInfo<IPtyHostAttachTarget | null>[]): Promise<ITerminalGroup | undefined> {
|
||||
@@ -502,7 +511,6 @@ export class TerminalService implements ITerminalService {
|
||||
});
|
||||
group = lastInstance.then(instance => this._terminalGroupService.getGroupForInstance(instance));
|
||||
} else {
|
||||
// TODO: Make parentInstance a promise?
|
||||
// add split terminals to this group
|
||||
lastInstance = this.createTerminal({
|
||||
config: { attachPersistentProcess },
|
||||
|
||||
@@ -280,6 +280,7 @@ export interface ITerminalProcessManager extends IDisposable {
|
||||
readonly onProcessReady: Event<IProcessReadyEvent>;
|
||||
readonly onBeforeProcessData: Event<IBeforeProcessDataEvent>;
|
||||
readonly onProcessData: Event<IProcessDataEvent>;
|
||||
readonly onProcessReplayComplete: Event<void>;
|
||||
readonly onEnvironmentVariableInfoChanged: Event<IEnvironmentVariableInfo>;
|
||||
readonly onDidChangeProperty: Event<IProcessProperty<any>>;
|
||||
readonly onProcessExit: Event<number | undefined>;
|
||||
|
||||
@@ -32,8 +32,8 @@ export class LocalPty extends Disposable implements ITerminalChildProcess {
|
||||
|
||||
private readonly _onProcessData = this._register(new Emitter<IProcessDataEvent | string>());
|
||||
readonly onProcessData = this._onProcessData.event;
|
||||
private readonly _onProcessReplay = this._register(new Emitter<IPtyHostProcessReplayEvent>());
|
||||
readonly onProcessReplay = this._onProcessReplay.event;
|
||||
private readonly _onProcessReplayComplete = this._register(new Emitter<void>());
|
||||
readonly onProcessReplayComplete = this._onProcessReplayComplete.event;
|
||||
private readonly _onProcessReady = this._register(new Emitter<IProcessReadyEvent>());
|
||||
readonly onProcessReady = this._onProcessReady.event;
|
||||
private readonly _onDidChangeProperty = this._register(new Emitter<IProcessProperty<any>>());
|
||||
@@ -162,6 +162,8 @@ export class LocalPty extends Disposable implements ITerminalChildProcess {
|
||||
|
||||
// remove size override
|
||||
this._onDidChangeProperty.fire({ type: ProcessPropertyType.OverrideDimensions, value: undefined });
|
||||
|
||||
this._onProcessReplayComplete.fire();
|
||||
}
|
||||
|
||||
handleOrphanQuestion() {
|
||||
|
||||
Reference in New Issue
Block a user