Wait to signal to the extHostTerminalService that the terminal is opened until the terminal has a name. (#58983)

Also added a change listener for title. Fixes #53057
This commit is contained in:
Alex Ross
2018-09-21 14:08:38 -07:00
committed by GitHub
parent 4cd9739394
commit 1ff175f094
7 changed files with 52 additions and 18 deletions

View File

@@ -585,16 +585,6 @@ suite('window namespace tests', () => {
});
suite('Terminal', () => {
test('createTerminal, Terminal.name', () => {
const terminal = window.createTerminal('foo');
assert.equal(terminal.name, 'foo');
assert.throws(() => {
(<any>terminal).name = 'bar';
}, 'Terminal.name should be readonly');
terminal.dispose();
});
test('sendText immediately after createTerminal should not throw', () => {
const terminal = window.createTerminal();
assert.doesNotThrow(terminal.sendText.bind(terminal, 'echo "foo"'));
@@ -708,10 +698,12 @@ suite('window namespace tests', () => {
test('onDidChangeActiveTerminal should fire when new terminals are created', (done) => {
const reg1 = window.onDidChangeActiveTerminal((active: Terminal | undefined) => {
console.log('!!!!!!!!!!!!!!!ONE');
assert.equal(active, terminal);
assert.equal(active, window.activeTerminal);
reg1.dispose();
const reg2 = window.onDidChangeActiveTerminal((active: Terminal | undefined) => {
console.log('!!!!!!!!!!!!!!!TWO');
assert.equal(active, undefined);
assert.equal(active, window.activeTerminal);
reg2.dispose();
@@ -721,6 +713,8 @@ suite('window namespace tests', () => {
});
const terminal = window.createTerminal();
terminal.show();
console.log('!!!!!!!!!!!!!!!THREE');
});
});
});

View File

@@ -35,6 +35,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._toDispose.push(terminalService.onInstanceDimensionsChanged(instance => this._onInstanceDimensionsChanged(instance)));
this._toDispose.push(terminalService.onInstanceRequestExtHostProcess(request => this._onTerminalRequestExtHostProcess(request)));
this._toDispose.push(terminalService.onActiveInstanceChanged(instance => this._onActiveTerminalChanged(instance ? instance.id : undefined)));
this._toDispose.push(terminalService.onInstanceTitleChanged(instance => this._onTitleChanged(instance.id, instance.title)));
// Set initial ext host state
this.terminalService.terminalInstances.forEach(t => {
@@ -163,6 +164,10 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._proxy.$acceptTerminalProcessData(terminalId, data);
}
private _onTitleChanged(terminalId: number, name: string): void {
this._proxy.$acceptTerminalTitleChange(terminalId, name);
}
private _onTerminalRendererInput(terminalId: number, data: string): void {
this._proxy.$acceptTerminalRendererInput(terminalId, data);
}
@@ -172,7 +177,13 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
}
private _onTerminalOpened(terminalInstance: ITerminalInstance): void {
this._proxy.$acceptTerminalOpened(terminalInstance.id, terminalInstance.title);
if (terminalInstance.title) {
this._proxy.$acceptTerminalOpened(terminalInstance.id, terminalInstance.title);
} else {
terminalInstance.waitForTitle().then(title => {
this._proxy.$acceptTerminalOpened(terminalInstance.id, title);
});
}
}
private _onTerminalProcessIdReady(terminalInstance: ITerminalInstance): void {

View File

@@ -879,6 +879,7 @@ export interface ExtHostTerminalServiceShape {
$acceptTerminalProcessId(id: number, processId: number): void;
$acceptTerminalProcessData(id: number, data: string): void;
$acceptTerminalRendererInput(id: number, data: string): void;
$acceptTerminalTitleChange(id: number, name: string): void;
$acceptTerminalRendererDimensions(id: number, cols: number, rows: number): void;
$createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, cols: number, rows: number): void;
$acceptProcessInput(id: number, data: string): void;

View File

@@ -115,6 +115,10 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
return this._name;
}
public set name(name: string) {
this._name = name;
}
public get processId(): Thenable<number> {
return this._pidPromise;
}
@@ -313,6 +317,13 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
}
public $acceptTerminalTitleChange(id: number, name: string): void {
const extHostTerminal = this._getTerminalObjectById(this.terminals, id);
if (extHostTerminal) {
extHostTerminal.name = name;
}
}
public $acceptTerminalClosed(id: number): void {
const index = this._getTerminalObjectIndexById(this.terminals, id);
if (index === null) {

View File

@@ -189,7 +189,7 @@ export interface ITerminalService {
onInstanceDimensionsChanged: Event<ITerminalInstance>;
onInstanceRequestExtHostProcess: Event<ITerminalProcessExtHostRequest>;
onInstancesChanged: Event<void>;
onInstanceTitleChanged: Event<string>;
onInstanceTitleChanged: Event<ITerminalInstance>;
onActiveInstanceChanged: Event<ITerminalInstance>;
terminalInstances: ITerminalInstance[];
terminalTabs: ITerminalTab[];
@@ -311,7 +311,7 @@ export interface ITerminalInstance {
/**
* An event that fires when the terminal instance's title changes.
*/
onTitleChanged: Event<string>;
onTitleChanged: Event<ITerminalInstance>;
/**
* An event that fires when the terminal instance is disposed.
@@ -569,6 +569,8 @@ export interface ITerminalInstance {
*/
setTitle(title: string, eventFromProcess: boolean): void;
waitForTitle(): Promise<string>;
setDimensions(dimensions: ITerminalDimensions): void;
addDisposable(disposable: IDisposable): void;

View File

@@ -44,8 +44,8 @@ export abstract class TerminalService implements ITerminalService {
public get onInstanceDimensionsChanged(): Event<ITerminalInstance> { return this._onInstanceDimensionsChanged.event; }
protected readonly _onInstancesChanged: Emitter<void> = new Emitter<void>();
public get onInstancesChanged(): Event<void> { return this._onInstancesChanged.event; }
protected readonly _onInstanceTitleChanged: Emitter<string> = new Emitter<string>();
public get onInstanceTitleChanged(): Event<string> { return this._onInstanceTitleChanged.event; }
protected readonly _onInstanceTitleChanged: Emitter<ITerminalInstance> = new Emitter<ITerminalInstance>();
public get onInstanceTitleChanged(): Event<ITerminalInstance> { return this._onInstanceTitleChanged.event; }
protected readonly _onActiveInstanceChanged: Emitter<ITerminalInstance> = new Emitter<ITerminalInstance>();
public get onActiveInstanceChanged(): Event<ITerminalInstance> { return this._onActiveInstanceChanged.event; }
protected readonly _onTabDisposed: Emitter<ITerminalTab> = new Emitter<ITerminalTab>();

View File

@@ -66,6 +66,8 @@ export class TerminalInstance implements ITerminalInstance {
private _dimensionsOverride: ITerminalDimensions;
private _windowsShellHelper: WindowsShellHelper;
private _xtermReadyPromise: Promise<void>;
private _titleReadyPromise: Promise<string>;
private _titleReadyComplete: (title: string) => any;
private _disposables: lifecycle.IDisposable[];
private _messageTitleDisposable: lifecycle.IDisposable;
@@ -97,8 +99,8 @@ export class TerminalInstance implements ITerminalInstance {
public get onFocused(): Event<ITerminalInstance> { return this._onFocused.event; }
private readonly _onProcessIdReady: Emitter<ITerminalInstance> = new Emitter<ITerminalInstance>();
public get onProcessIdReady(): Event<ITerminalInstance> { return this._onProcessIdReady.event; }
private readonly _onTitleChanged: Emitter<string> = new Emitter<string>();
public get onTitleChanged(): Event<string> { return this._onTitleChanged.event; }
private readonly _onTitleChanged: Emitter<ITerminalInstance> = new Emitter<ITerminalInstance>();
public get onTitleChanged(): Event<ITerminalInstance> { return this._onTitleChanged.event; }
private readonly _onData: Emitter<string> = new Emitter<string>();
public get onData(): Event<string> { return this._onData.event; }
private readonly _onLineData: Emitter<string> = new Emitter<string>();
@@ -135,6 +137,11 @@ export class TerminalInstance implements ITerminalInstance {
this._isVisible = false;
this._isDisposed = false;
this._id = TerminalInstance._idCounter++;
this._titleReadyPromise = new Promise<string>(c => {
this._titleReadyComplete = c;
});
this._terminalHasTextContextKey = KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED.bindTo(this._contextKeyService);
this.disableLayout = false;
@@ -1031,12 +1038,20 @@ export class TerminalInstance implements ITerminalInstance {
}
}
const didTitleChange = title !== this._title;
const oldTitle = this._title;
this._title = title;
if (didTitleChange) {
this._onTitleChanged.fire(title);
if (!oldTitle) {
this._titleReadyComplete(title);
}
this._onTitleChanged.fire(this);
}
}
public waitForTitle(): Promise<string> {
return this._titleReadyPromise;
}
public setDimensions(dimensions: ITerminalDimensions): void {
this._dimensionsOverride = dimensions;
this._resize();