Skip to content

Commit 09e7f4e

Browse files
committed
Preserve focus in status bar
fixes microsoft#97241
1 parent 9b18ead commit 09e7f4e

3 files changed

Lines changed: 36 additions & 6 deletions

File tree

src/vs/workbench/browser/layout.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
178178
private notificationService!: INotificationService;
179179
private themeService!: IThemeService;
180180
private activityBarService!: IActivityBarService;
181+
private statusBarService!: IStatusbarService;
181182

182183
protected readonly state = {
183184
fullscreen: false,
@@ -262,7 +263,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
262263
this.titleService = accessor.get(ITitleService);
263264
this.notificationService = accessor.get(INotificationService);
264265
this.activityBarService = accessor.get(IActivityBarService);
265-
accessor.get(IStatusbarService); // not used, but called to ensure instantiated
266+
this.statusBarService = accessor.get(IStatusbarService);
266267

267268
// Listeners
268269
this.registerLayoutListeners();
@@ -850,8 +851,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
850851
case Parts.ACTIVITYBAR_PART:
851852
this.activityBarService.focusActivityBar();
852853
break;
854+
case Parts.STATUSBAR_PART:
855+
this.statusBarService.focus();
853856
default:
854-
// Status Bar, Activity Bar and Title Bar simply pass focus to container
857+
// Title Bar simply pass focus to container
855858
const container = this.getContainer(part);
856859
if (container) {
857860
container.focus();

src/vs/workbench/browser/parts/statusbar/statusbarPart.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class StatusbarViewModel extends Disposable {
6969
get entries(): IStatusbarViewModelEntry[] { return this._entries; }
7070

7171
private hidden!: Set<string>;
72+
get lastFocusedEntry(): IStatusbarViewModelEntry | undefined {
73+
return this._lastFocusedEntry && !this.isHidden(this._lastFocusedEntry.id) ? this._lastFocusedEntry : undefined;
74+
}
75+
private _lastFocusedEntry: IStatusbarViewModelEntry | undefined;
7276

7377
private readonly _onDidChangeEntryVisibility = this._register(new Emitter<{ id: string, visible: boolean }>());
7478
readonly onDidChangeEntryVisibility = this._onDidChangeEntryVisibility.event;
@@ -219,13 +223,15 @@ class StatusbarViewModel extends Disposable {
219223
if (focused) {
220224
const entry = getVisibleEntry(this._entries.indexOf(focused) + delta);
221225
if (entry) {
226+
this._lastFocusedEntry = entry;
222227
entry.labelContainer.focus();
223228
return;
224229
}
225230
}
226231

227232
const entry = getVisibleEntry(restartPosition);
228233
if (entry) {
234+
this._lastFocusedEntry = entry;
229235
entry.labelContainer.focus();
230236
}
231237
}
@@ -493,6 +499,15 @@ export class StatusbarPart extends Part implements IStatusbarService {
493499
this.viewModel.focusPreviousEntry();
494500
}
495501

502+
focus(preserveEntryFocus = true): void {
503+
this.getContainer()?.focus();
504+
const lastFocusedEntry = this.viewModel.lastFocusedEntry;
505+
if (preserveEntryFocus && lastFocusedEntry) {
506+
// Need a timeout, for some reason without it the inner label container will not get focused
507+
setTimeout(() => lastFocusedEntry.labelContainer.focus(), 0);
508+
}
509+
}
510+
496511
createContentArea(parent: HTMLElement): HTMLElement {
497512
this.element = parent;
498513

@@ -680,10 +695,6 @@ export class StatusbarPart extends Part implements IStatusbarService {
680695
return itemContainer;
681696
}
682697

683-
focus(): void {
684-
this.getContainer();
685-
}
686-
687698
layout(width: number, height: number): void {
688699
super.layout(width, height);
689700
super.layoutContents(width, height);
@@ -935,3 +946,14 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
935946
statusBarService.focusNextEntry();
936947
}
937948
});
949+
950+
KeybindingsRegistry.registerCommandAndKeybindingRule({
951+
id: 'workbench.statusBar.clearFocus',
952+
weight: KeybindingWeight.WorkbenchContrib,
953+
primary: KeyCode.Escape,
954+
when: CONTEXT_STATUS_BAR_FOCUSED,
955+
handler: (accessor: ServicesAccessor) => {
956+
const statusBarService = accessor.get(IStatusbarService);
957+
statusBarService.focus(false);
958+
}
959+
});

src/vs/workbench/services/statusbar/common/statusbar.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ export interface IStatusbarService {
9090
*/
9191
updateEntryVisibility(id: string, visible: boolean): void;
9292

93+
/**
94+
* Focused the status bar. If one of the status bar entries was focused, focuses it directly.
95+
*/
96+
focus(preserveEntryFocus?: boolean): void;
97+
9398
/**
9499
* Focuses the next status bar entry. If none focused, focuses the first.
95100
*/

0 commit comments

Comments
 (0)