Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Working sets - add preserveFocus #213397

Merged
merged 5 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions src/vs/workbench/browser/parts/editor/editorGroupView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,16 @@ export class EditorGroupView extends Themable implements IEditorGroupView {

//#region factory

static createNew(editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService): IEditorGroupView {
return instantiationService.createInstance(EditorGroupView, null, editorPartsView, groupsView, groupsLabel, groupIndex);
static createNew(editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService, preserveFocus?: boolean): IEditorGroupView {
return instantiationService.createInstance(EditorGroupView, null, editorPartsView, groupsView, groupsLabel, groupIndex, preserveFocus);
}

static createFromSerialized(serialized: ISerializedEditorGroupModel, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService): IEditorGroupView {
return instantiationService.createInstance(EditorGroupView, serialized, editorPartsView, groupsView, groupsLabel, groupIndex);
static createFromSerialized(serialized: ISerializedEditorGroupModel, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService, preserveFocus?: boolean): IEditorGroupView {
return instantiationService.createInstance(EditorGroupView, serialized, editorPartsView, groupsView, groupsLabel, groupIndex, preserveFocus);
}

static createCopy(copyFrom: IEditorGroupView, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService): IEditorGroupView {
return instantiationService.createInstance(EditorGroupView, copyFrom, editorPartsView, groupsView, groupsLabel, groupIndex);
static createCopy(copyFrom: IEditorGroupView, editorPartsView: IEditorPartsView, groupsView: IEditorGroupsView, groupsLabel: string, groupIndex: number, instantiationService: IInstantiationService, preserveFocus?: boolean): IEditorGroupView {
return instantiationService.createInstance(EditorGroupView, copyFrom, editorPartsView, groupsView, groupsLabel, groupIndex, preserveFocus);
}

//#endregion
Expand Down Expand Up @@ -145,6 +145,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
readonly groupsView: IEditorGroupsView,
private groupsLabel: string,
private _index: number,
private preserveFocus: boolean | undefined,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
Expand Down Expand Up @@ -236,7 +237,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
//#endregion

// Restore editors if provided
const restoreEditorsPromise = this.restoreEditors(from) ?? Promise.resolve();
const restoreEditorsPromise = this.restoreEditors(from, preserveFocus) ?? Promise.resolve();

// Signal restored once editors have restored
restoreEditorsPromise.finally(() => {
Expand Down Expand Up @@ -534,7 +535,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
this.titleContainer.classList.toggle('show-file-icons', this.groupsView.partOptions.showIcons);
}

private restoreEditors(from: IEditorGroupView | ISerializedEditorGroupModel | null): Promise<void> | undefined {
private restoreEditors(from: IEditorGroupView | ISerializedEditorGroupModel | null, preserveFocus: boolean | undefined): Promise<void> | undefined {
if (this.count === 0) {
return; // nothing to show
}
Expand Down Expand Up @@ -571,7 +572,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
// stolen accidentally on startup when the user already
// clicked somewhere.

if (this.groupsView.activeGroup === this && activeElement && isActiveElement(activeElement)) {
if (this.groupsView.activeGroup === this && activeElement && isActiveElement(activeElement) && this.preserveFocus === false) {
this.focus();
}
});
Expand Down
24 changes: 12 additions & 12 deletions src/vs/workbench/browser/parts/editor/editorPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -615,16 +615,16 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
}
}

private doCreateGroupView(from?: IEditorGroupView | ISerializedEditorGroupModel | null): IEditorGroupView {
private doCreateGroupView(from?: IEditorGroupView | ISerializedEditorGroupModel | null, preserveFocus?: boolean): IEditorGroupView {

// Create group view
let groupView: IEditorGroupView;
if (from instanceof EditorGroupView) {
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService,);
groupView = EditorGroupView.createCopy(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService, preserveFocus);
} else if (isSerializedEditorGroupModel(from)) {
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
groupView = EditorGroupView.createFromSerialized(from, this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService, preserveFocus);
} else {
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService);
groupView = EditorGroupView.createNew(this.editorPartsView, this, this.groupsLabel, this.count, this.scopedInstantiationService, preserveFocus);
}

// Keep in map
Expand Down Expand Up @@ -1192,7 +1192,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
return true; // success
}

private doCreateGridControlWithState(serializedGrid: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[]): void {
private doCreateGridControlWithState(serializedGrid: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[], preserveFocus?: boolean): void {

// Determine group views to reuse if any
let reuseGroupViews: IEditorGroupView[];
Expand All @@ -1210,7 +1210,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
if (reuseGroupViews.length > 0) {
groupView = reuseGroupViews.shift()!;
} else {
groupView = this.doCreateGroupView(serializedEditorGroup);
groupView = this.doCreateGroupView(serializedEditorGroup, preserveFocus);
}

groupViews.push(groupView);
Expand Down Expand Up @@ -1342,15 +1342,15 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
};
}

applyState(state: IEditorPartUIState | 'empty'): Promise<void> {
applyState(state: IEditorPartUIState | 'empty', preserveFocus?: boolean): Promise<void> {
if (state === 'empty') {
return this.doApplyEmptyState();
} else {
return this.doApplyState(state);
return this.doApplyState(state, preserveFocus);
}
}

private async doApplyState(state: IEditorPartUIState): Promise<void> {
private async doApplyState(state: IEditorPartUIState, preserveFocus?: boolean): Promise<void> {
const groups = await this.doPrepareApplyState();
const resumeEvents = this.disposeGroups(true /* suspress events for the duration of applying state */);

Expand All @@ -1359,7 +1359,7 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {

// Grid Widget
try {
this.doApplyGridState(state.serializedGrid, state.activeGroup);
this.doApplyGridState(state.serializedGrid, state.activeGroup, undefined, preserveFocus);
} finally {
resumeEvents();
}
Expand Down Expand Up @@ -1396,10 +1396,10 @@ export class EditorPart extends Part implements IEditorPart, IEditorGroupsView {
return groups;
}

private doApplyGridState(gridState: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[]): void {
private doApplyGridState(gridState: ISerializedGrid, activeGroupId: GroupIdentifier, editorGroupViewsToReuse?: IEditorGroupView[], preserveFocus?: boolean): void {

// Recreate grid widget from state
this.doCreateGridControlWithState(gridState, activeGroupId, editorGroupViewsToReuse);
this.doCreateGridControlWithState(gridState, activeGroupId, editorGroupViewsToReuse, preserveFocus);

// Layout
this.doLayout(this._contentDimension);
Expand Down
22 changes: 16 additions & 6 deletions src/vs/workbench/browser/parts/editor/editorParts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IAuxiliaryWindowOpenOptions, IAuxiliaryWindowService } from 'vs/workbench/services/auxiliaryWindow/browser/auxiliaryWindowService';
import { generateUuid } from 'vs/base/common/uuid';
import { ContextKeyValue, IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';

interface IEditorPartsUIState {
readonly auxiliary: IAuxiliaryEditorPartState[];
Expand Down Expand Up @@ -50,7 +51,8 @@ export class EditorParts extends MultiWindowParts<EditorPart> implements IEditor
@IStorageService private readonly storageService: IStorageService,
@IThemeService themeService: IThemeService,
@IAuxiliaryWindowService private readonly auxiliaryWindowService: IAuxiliaryWindowService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService
) {
super('workbench.editorParts', themeService, storageService);

Expand Down Expand Up @@ -387,6 +389,12 @@ export class EditorParts extends MultiWindowParts<EditorPart> implements IEditor
return false;
}

// Applying a working set can be the result of a user action that has been
// initiated from the terminal (ex: switching branches). As such, we want
// to preserve the focus in the terminal. This does not cover the scenario
// in which the terminal is in the editor part.
const preserveFocus = this.layoutService.hasFocus(Parts.PANEL_PART);

// Apply state: begin with auxiliary windows first because it helps to keep
// editors around that need confirmation by moving them into the main part.
// Also, in rare cases, the auxiliary part may not be able to apply the state
Expand All @@ -395,13 +403,15 @@ export class EditorParts extends MultiWindowParts<EditorPart> implements IEditor
if (!applied) {
return false;
}
await this.mainPart.applyState(workingSetState === 'empty' ? workingSetState : workingSetState.main);
await this.mainPart.applyState(workingSetState === 'empty' ? workingSetState : workingSetState.main, preserveFocus);

// Restore Focus
const mostRecentActivePart = firstOrDefault(this.mostRecentActiveParts);
if (mostRecentActivePart) {
await mostRecentActivePart.whenReady;
mostRecentActivePart.activeGroup.focus();
if (!preserveFocus) {
const mostRecentActivePart = firstOrDefault(this.mostRecentActiveParts);
if (mostRecentActivePart) {
await mostRecentActivePart.whenReady;
mostRecentActivePart.activeGroup.focus();
}
}

return true;
Expand Down
Loading