diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index bb0d6570508c650a29d6f374d8b851e6ef4fd857..e8d196a218b1257b9943b22c129695188459afbe 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -178,6 +178,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi private notificationService!: INotificationService; private themeService!: IThemeService; private activityBarService!: IActivityBarService; + private statusBarService!: IStatusbarService; protected readonly state = { fullscreen: false, @@ -262,7 +263,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi this.titleService = accessor.get(ITitleService); this.notificationService = accessor.get(INotificationService); this.activityBarService = accessor.get(IActivityBarService); - accessor.get(IStatusbarService); // not used, but called to ensure instantiated + this.statusBarService = accessor.get(IStatusbarService); // Listeners this.registerLayoutListeners(); @@ -850,8 +851,10 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi case Parts.ACTIVITYBAR_PART: this.activityBarService.focusActivityBar(); break; + case Parts.STATUSBAR_PART: + this.statusBarService.focus(); default: - // Status Bar, Activity Bar and Title Bar simply pass focus to container + // Title Bar simply pass focus to container const container = this.getContainer(part); if (container) { container.focus(); diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 2b74fcdbd38c23ea5697a692ee20a6d9bca0dae5..fa4de06a425dd864842bfc26b0a426dc0df6b184 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -69,6 +69,10 @@ class StatusbarViewModel extends Disposable { get entries(): IStatusbarViewModelEntry[] { return this._entries; } private hidden!: Set; + get lastFocusedEntry(): IStatusbarViewModelEntry | undefined { + return this._lastFocusedEntry && !this.isHidden(this._lastFocusedEntry.id) ? this._lastFocusedEntry : undefined; + } + private _lastFocusedEntry: IStatusbarViewModelEntry | undefined; private readonly _onDidChangeEntryVisibility = this._register(new Emitter<{ id: string, visible: boolean }>()); readonly onDidChangeEntryVisibility = this._onDidChangeEntryVisibility.event; @@ -219,6 +223,7 @@ class StatusbarViewModel extends Disposable { if (focused) { const entry = getVisibleEntry(this._entries.indexOf(focused) + delta); if (entry) { + this._lastFocusedEntry = entry; entry.labelContainer.focus(); return; } @@ -226,6 +231,7 @@ class StatusbarViewModel extends Disposable { const entry = getVisibleEntry(restartPosition); if (entry) { + this._lastFocusedEntry = entry; entry.labelContainer.focus(); } } @@ -493,6 +499,15 @@ export class StatusbarPart extends Part implements IStatusbarService { this.viewModel.focusPreviousEntry(); } + focus(preserveEntryFocus = true): void { + this.getContainer()?.focus(); + const lastFocusedEntry = this.viewModel.lastFocusedEntry; + if (preserveEntryFocus && lastFocusedEntry) { + // Need a timeout, for some reason without it the inner label container will not get focused + setTimeout(() => lastFocusedEntry.labelContainer.focus(), 0); + } + } + createContentArea(parent: HTMLElement): HTMLElement { this.element = parent; @@ -680,10 +695,6 @@ export class StatusbarPart extends Part implements IStatusbarService { return itemContainer; } - focus(): void { - this.getContainer(); - } - layout(width: number, height: number): void { super.layout(width, height); super.layoutContents(width, height); @@ -935,3 +946,14 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ statusBarService.focusNextEntry(); } }); + +KeybindingsRegistry.registerCommandAndKeybindingRule({ + id: 'workbench.statusBar.clearFocus', + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyCode.Escape, + when: CONTEXT_STATUS_BAR_FOCUSED, + handler: (accessor: ServicesAccessor) => { + const statusBarService = accessor.get(IStatusbarService); + statusBarService.focus(false); + } +}); diff --git a/src/vs/workbench/services/statusbar/common/statusbar.ts b/src/vs/workbench/services/statusbar/common/statusbar.ts index 7a90dfab5f3f5474f774bc98ea260d068c52f641..af13535d6227c684690f23001891ab7e65ca1887 100644 --- a/src/vs/workbench/services/statusbar/common/statusbar.ts +++ b/src/vs/workbench/services/statusbar/common/statusbar.ts @@ -90,6 +90,11 @@ export interface IStatusbarService { */ updateEntryVisibility(id: string, visible: boolean): void; + /** + * Focused the status bar. If one of the status bar entries was focused, focuses it directly. + */ + focus(preserveEntryFocus?: boolean): void; + /** * Focuses the next status bar entry. If none focused, focuses the first. */