Change:
Testing It would be great if we can have a command to bring back those editors to the main window.
I think that should actually be the default behaviour when you just close the window. That will prevent ugly confirmation dialogs for dirty editors when you attempt to close the floating window.
Verification: open a floating window with some editors (e.g. by dragging an editor tab out of the window) close the floating window, e.g. from the X window button verify all editors of the floating window are moved back to the main window

Discussion:
*/ export interface IEditorPartsView { <del> /** * An array of all editor groups across all editor parts. */ readonly groups: IEditorGroupView[]; </del> <ins> readonly mainPart: IEditorGroupsView; </ins> <del> /** * Get the group based on an identifier across all opened * editor parts. */ </del> <ins> readonly activeGroup: IEditorGroupView; readonly groups: IEditorGroupView[]; </ins> getGroup(identifier: GroupIdentifier): IEditorGroupView | undefined; <ins> mergeGroup(group: IEditorGroupView, target: IEditorGroupView, options?: IMergeGroupOptions): IEditorGroupView; </ins> } /**

private readonly gridWidgetView = this._register(new GridWidgetView<IEditorGroupView>()); constructor( <del> private readonly editorPartsView: IEditorPartsView, </del> <ins> protected readonly editorPartsView: IEditorPartsView, </ins> id: string, private readonly groupsLabel: string, public readonly isAuxiliary: boolean,

// Close aux window when last group removed const groupView = this.assertGroupView(group); if (this.count === 1 && this.activeGroup === groupView) { <del> this.close(); </del> <ins> this.doClose(false /* do not merge any groups to main part */); </ins> } // Otherwise delegate to parent implementation

return; // TODO support auxiliary editor state } <del> async close(): Promise<void> { // TODO this needs full support for closing all editors, handling vetos and showing dialogs </del> <ins> close(): void { this.doClose(true /* merge all groups to main part */); } private doClose(mergeGroupsToMainPart: boolean): void { if (mergeGroupsToMainPart) { for (const group of this.groups) { this.editorPartsView.mergeGroup(group, this.editorPartsView.mainPart.activeGroup); } } </ins> this._onDidClose.fire(); } }

const disposables = new DisposableStore(); const auxiliaryWindow = disposables.add(await this.auxiliaryWindowService.open(options)); <del> disposables.add(Event.once(auxiliaryWindow.onDidClose)(() => disposables.dispose())); </del> const partContainer = document.createElement('div'); partContainer.classList.add('part', 'editor');

const editorPart = disposables.add(this.instantiationService.createInstance(AuxiliaryEditorPart, this, this.getGroupsLabel(this._parts.size))); disposables.add(this.registerEditorPart(editorPart)); <ins> editorPart.create(partContainer, { restorePreviousState: false }); disposables.add(this.instantiationService.createInstance(WindowTitle, auxiliaryWindow.window, editorPart)); disposables.add(Event.once(auxiliaryWindow.onWillClose)(() => { if (disposables.isDisposed) { return; // the close happened as part of an earlier dispose call } editorPart.close(); disposables.dispose(); })); </ins> disposables.add(Event.once(editorPart.onDidClose)(() => disposables.dispose())); disposables.add(Event.once(this.lifecycleService.onDidShutdown)(() => disposables.dispose())); <del> editorPart.create(partContainer, { restorePreviousState: false }); disposables.add(this.instantiationService.createInstance(WindowTitle, auxiliaryWindow.window, editorPart)); </del> disposables.add(auxiliaryWindow.onDidLayout(dimension => editorPart.layout(dimension.width, dimension.height, 0, 0))); auxiliaryWindow.layout();

export interface IAuxiliaryWindow extends IDisposable { readonly onDidLayout: Event<Dimension>; <del> readonly onDidClose: Event<void>; </del> <ins> readonly onWillClose: Event<void>; </ins> readonly window: CodeWindow; readonly container: HTMLElement;

private readonly _onDidLayout = this._register(new Emitter<Dimension>()); readonly onDidLayout = this._onDidLayout.event; <del> private readonly _onDidClose = this._register(new Emitter<void>()); readonly onDidClose = this._onDidClose.event; </del> <ins> private readonly _onWillClose = this._register(new Emitter<void>()); readonly onWillClose = this._onWillClose.event; </ins> private readonly _onWillDispose = this._register(new Emitter<void>()); readonly onWillDispose = this._onWillDispose.event;

} private registerListeners(): void { <del> this._register(addDisposableListener(this.window, 'unload', () => { this._onDidClose.fire(); </del> <ins> this._register(addDisposableListener(this.window, 'beforeunload', () => { this._onWillClose.fire(); </ins> })); this._register(addDisposableListener(this.window, 'unhandledrejection', e => {

export interface IAuxiliaryEditorPart extends IEditorPart { /** <del> * Close this auxiliary editor part and free up associated resources. </del> <ins> * Close this auxiliary editor part after moving all * editors of all groups back to the main editor part. </ins> */ <del> close(): Promise<void>; </del> <ins> close(): void; </ins> } /**