diff --git a/src/vs/workbench/browser/media/style.css b/src/vs/workbench/browser/media/style.css index 1f6e583f5e0be..10447338529bf 100644 --- a/src/vs/workbench/browser/media/style.css +++ b/src/vs/workbench/browser/media/style.css @@ -32,6 +32,9 @@ .monaco-workbench.windows { --monaco-monospace-font: Consolas, "Courier New", monospace; } .monaco-workbench.linux { --monaco-monospace-font: "Ubuntu Mono", "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace; } +/* Applied when workbench.fontFamily is set — overrides platform defaults */ +.monaco-workbench.monaco-workbench-custom-font { font-family: var(--vscode-workbench-font-family) !important; } + /* Global Styles */ body { @@ -46,7 +49,7 @@ body { } .monaco-workbench { - font-size: 13px; + font-size: var(--vscode-workbench-font-size, 13px); line-height: 1.4em; position: relative; inset: 0; diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index eeddba006261b..95ab7ae2d9528 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -700,6 +700,20 @@ const registry = Registry.as(ConfigurationExtensions.Con }, 'additionalProperties': false }, + 'workbench.fontSize': { + 'type': 'number', + 'default': 13, + 'minimum': 8, + 'maximum': 30, + 'description': localize('workbench.fontSize', "Controls the font size in pixels of the workbench UI (sidebar, tabs, status bar, etc.). Does not affect the editor font size (use `editor.fontSize` for that)."), + 'scope': ConfigurationScope.APPLICATION + }, + 'workbench.fontFamily': { + 'type': 'string', + 'default': '', + 'description': localize('workbench.fontFamily', "Controls the font family of the workbench UI. When set, overrides the platform default font. Leave empty to use the platform default."), + 'scope': ConfigurationScope.APPLICATION + }, 'workbench.fontAliasing': { 'type': 'string', 'enum': ['default', 'antialiased', 'none', 'auto'], diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts index 10e2c3edace79..f1659f1bbc76d 100644 --- a/src/vs/workbench/browser/workbench.ts +++ b/src/vs/workbench/browser/workbench.ts @@ -231,7 +231,11 @@ export class Workbench extends Layout { private registerListeners(lifecycleService: ILifecycleService, storageService: IStorageService, configurationService: IConfigurationService, hostService: IHostService, dialogService: IDialogService): void { // Configuration changes - this._register(configurationService.onDidChangeConfiguration(e => this.updateFontAliasing(e, configurationService))); + this._register(configurationService.onDidChangeConfiguration(e => { + this.updateFontAliasing(e, configurationService); + this.updateWorkbenchFontSize(e, configurationService); + this.updateWorkbenchFontFamily(e, configurationService); + })); // Font Info if (isNative) { @@ -294,6 +298,46 @@ export class Workbench extends Layout { } } + private workbenchFontSize: number | undefined; + private updateWorkbenchFontSize(e: IConfigurationChangeEvent | undefined, configurationService: IConfigurationService): void { + if (e && !e.affectsConfiguration('workbench.fontSize')) { + return; + } + + const raw = configurationService.getValue('workbench.fontSize'); + const size = (typeof raw === 'number' && raw >= 8 && raw <= 30) ? raw : 13; + if (this.workbenchFontSize === size) { + return; + } + + this.workbenchFontSize = size; + this.mainContainer.style.setProperty('--vscode-workbench-font-size', `${size}px`); + } + + private workbenchFontFamily: string | undefined; + private updateWorkbenchFontFamily(e: IConfigurationChangeEvent | undefined, configurationService: IConfigurationService): void { + if (e && !e.affectsConfiguration('workbench.fontFamily')) { + return; + } + + const raw = configurationService.getValue('workbench.fontFamily'); + // Strip characters that could form CSS injection vectors before embedding + // the value into a custom property (semicolons, braces, angle brackets, newlines). + const family = typeof raw === 'string' ? raw.trim().replace(/[;{}<>\n\r]/g, '') : ''; + if (this.workbenchFontFamily === family) { + return; + } + + this.workbenchFontFamily = family; + if (family) { + this.mainContainer.style.setProperty('--vscode-workbench-font-family', family); + this.mainContainer.classList.add('monaco-workbench-custom-font'); + } else { + this.mainContainer.style.removeProperty('--vscode-workbench-font-family'); + this.mainContainer.classList.remove('monaco-workbench-custom-font'); + } + } + private restoreFontInfo(storageService: IStorageService, configurationService: IConfigurationService): void { const storedFontInfoRaw = storageService.get('editorFontInfo', StorageScope.APPLICATION); if (storedFontInfoRaw) { @@ -339,6 +383,10 @@ export class Workbench extends Layout { // Apply font aliasing this.updateFontAliasing(undefined, configurationService); + // Apply workbench font size and family + this.updateWorkbenchFontSize(undefined, configurationService); + this.updateWorkbenchFontFamily(undefined, configurationService); + // Warm up font cache information before building up too many dom elements this.restoreFontInfo(storageService, configurationService);