mirror of
https://github.com/VSCodium/vscodium.git
synced 2026-04-13 20:28:18 +10:00
feat: add patches for per-area font customization
Three new patches extending workbench font customization to all areas: - feat-workbench-zz-area-font-family: fontFamily for sidebar, statusbar, tabs, panel, activitybar + global fontSize setting - feat-workbench-zz-area-font-size-core: fontSize for statusbar, activitybar, panel with proportional scaling via FONT object - feat-workbench-zz-area-font-size-tabs: fontSize for tabs with CSS variable scaling for tab heights and widths Includes fixes from audit review: - Fix stale CSS var when fontSize reverts to default (cache isUserSet) - Fix else-if config listener blocking simultaneous updates - Trigger grid relayout after statusbar font-size change - Apply activitybar font before show() for correct initial sizing - Trigger tab relayout after font-size change - Standardize CSS fallback chains to include global font-size - Extract inspectFontSize() helper to reduce duplication - Replace magic 1.833333 ratio with explicit CSS height variable
This commit is contained in:
477
patches/feat-workbench-zz-area-font-family.patch
Normal file
477
patches/feat-workbench-zz-area-font-family.patch
Normal file
@@ -0,0 +1,477 @@
|
||||
diff --git a/src/vs/workbench/browser/media/style.css b/src/vs/workbench/browser/media/style.css
|
||||
index 473c1f8..57ad58c 100644
|
||||
--- a/src/vs/workbench/browser/media/style.css
|
||||
+++ b/src/vs/workbench/browser/media/style.css
|
||||
@@ -54,6 +54,7 @@ body {
|
||||
overflow: hidden;
|
||||
color: var(--vscode-foreground);
|
||||
font-family: var(--vscode-workbench-font-family, var(--monaco-font));
|
||||
+ font-size: var(--vscode-workbench-font-size, 13px);
|
||||
}
|
||||
|
||||
.monaco-workbench.web {
|
||||
diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
|
||||
index 080b687..cbd14af 100644
|
||||
--- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
|
||||
@@ -38,6 +38,7 @@ import { IExtensionService } from '../../../services/extensions/common/extension
|
||||
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
|
||||
import { IViewsService } from '../../../services/views/common/viewsService.js';
|
||||
import { SwitchCompositeViewAction } from '../compositeBarActions.js';
|
||||
+import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
|
||||
export class ActivitybarPart extends Part {
|
||||
|
||||
@@ -65,8 +66,15 @@ export class ActivitybarPart extends Part {
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
+ @IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
+
|
||||
+ this._register(configurationService.onDidChangeConfiguration(e => {
|
||||
+ if (e.affectsConfiguration('workbench.activityBar.experimental.fontFamily')) {
|
||||
+ this.applyActivityBarFontFamily();
|
||||
+ }
|
||||
+ }));
|
||||
}
|
||||
|
||||
private createCompositeBar(): PaneCompositeBar {
|
||||
@@ -107,9 +115,24 @@ export class ActivitybarPart extends Part {
|
||||
this.show();
|
||||
}
|
||||
|
||||
+ this.applyActivityBarFontFamily(parent);
|
||||
+
|
||||
return this.content;
|
||||
}
|
||||
|
||||
+ private applyActivityBarFontFamily(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const family = this.configurationService.getValue<string>('workbench.activityBar.experimental.fontFamily');
|
||||
+ if (family) {
|
||||
+ target.style.setProperty('--vscode-workbench-activitybar-font-family', family);
|
||||
+ } else {
|
||||
+ target.style.removeProperty('--vscode-workbench-activitybar-font-family');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
getPinnedPaneCompositeIds(): string[] {
|
||||
return this.compositeBar.value?.getPinnedPaneCompositeIds() ?? [];
|
||||
}
|
||||
diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
|
||||
index abe1427..7cd25d0 100644
|
||||
--- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
|
||||
+++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
|
||||
@@ -6,6 +6,7 @@
|
||||
.monaco-workbench .part.activitybar {
|
||||
width: 48px;
|
||||
height: 100%;
|
||||
+ font-family: var(--vscode-workbench-activitybar-font-family, inherit);
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar.bordered::before {
|
||||
diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts
|
||||
index d3fa112..31d8df8 100644
|
||||
--- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarPart.ts
|
||||
@@ -137,6 +137,9 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
|
||||
if (e.affectsConfiguration(SidebarPart.fontSizeSettingsKey)) {
|
||||
this.applyAuxiliaryBarFontSize();
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.sideBar.experimental.fontFamily')) {
|
||||
+ this.applyAuxiliaryBarFontFamily();
|
||||
+ }
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -178,6 +181,20 @@ export class AuxiliaryBarPart extends AbstractPaneCompositePart {
|
||||
container.style.borderRightWidth = borderColor && isPositionLeft ? '1px' : '0px';
|
||||
|
||||
this.applyAuxiliaryBarFontSize(container);
|
||||
+ this.applyAuxiliaryBarFontFamily(container);
|
||||
+ }
|
||||
+
|
||||
+ private applyAuxiliaryBarFontFamily(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const family = this.configurationService.getValue<string>('workbench.sideBar.experimental.fontFamily');
|
||||
+ if (family) {
|
||||
+ target.style.setProperty('--vscode-workbench-sidebar-font-family', family);
|
||||
+ } else {
|
||||
+ target.style.removeProperty('--vscode-workbench-sidebar-font-family');
|
||||
+ }
|
||||
}
|
||||
|
||||
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
|
||||
diff --git a/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css b/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css
|
||||
index 6ec40df..398bbe1 100644
|
||||
--- a/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css
|
||||
+++ b/src/vs/workbench/browser/parts/auxiliarybar/media/auxiliaryBarPart.css
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
.monaco-workbench .part.auxiliarybar > .content {
|
||||
font-size: var(--vscode-workbench-sidebar-font-size, 13px);
|
||||
+ font-family: var(--vscode-workbench-sidebar-font-family, inherit);
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
diff --git a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
|
||||
index b0a44e2..a946cb7 100644
|
||||
--- a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
|
||||
+++ b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
|
||||
@@ -46,6 +46,7 @@ import { ServiceCollection } from '../../../../platform/instantiation/common/ser
|
||||
import { IBaseActionViewItemOptions } from '../../../../base/browser/ui/actionbar/actionViewItems.js';
|
||||
import { MarkdownString } from '../../../../base/common/htmlContent.js';
|
||||
import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
|
||||
+import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
import { applyDragImage } from '../../../../base/browser/ui/dnd/dnd.js';
|
||||
|
||||
export class EditorCommandsContextActionRunner extends ActionRunner {
|
||||
@@ -140,6 +141,7 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IEditorResolverService private readonly editorResolverService: IEditorResolverService,
|
||||
@IHostService private readonly hostService: IHostService,
|
||||
+ @IConfigurationService protected readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super(themeService);
|
||||
|
||||
@@ -147,6 +149,12 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
|
||||
|
||||
const container = this.create(parent);
|
||||
|
||||
+ this._register(configurationService.onDidChangeConfiguration(e => {
|
||||
+ if (e.affectsConfiguration('workbench.tabs.experimental.fontFamily')) {
|
||||
+ this.applyTabsFontFamily();
|
||||
+ }
|
||||
+ }));
|
||||
+
|
||||
// Context Keys
|
||||
this.contextMenuContextKeyService = this._register(this.contextKeyService.createScoped(container));
|
||||
const scopedInstantiationService = this._register(this.instantiationService.createChild(new ServiceCollection(
|
||||
@@ -169,9 +177,23 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
|
||||
|
||||
protected create(parent: HTMLElement): HTMLElement {
|
||||
this.updateTabHeight();
|
||||
+ this.applyTabsFontFamily(parent);
|
||||
return parent;
|
||||
}
|
||||
|
||||
+ private applyTabsFontFamily(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.parent;
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const family = this.configurationService.getValue<string>('workbench.tabs.experimental.fontFamily');
|
||||
+ if (family) {
|
||||
+ target.style.setProperty('--vscode-workbench-tabs-font-family', family);
|
||||
+ } else {
|
||||
+ target.style.removeProperty('--vscode-workbench-tabs-font-family');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private get editorActionsEnabled(): boolean {
|
||||
return this.groupsView.partOptions.editorActionsLocation === 'default' && this.groupsView.partOptions.showTabs !== 'none';
|
||||
}
|
||||
diff --git a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
|
||||
index 57ab8ca..e9e0b2b 100644
|
||||
--- a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
|
||||
+++ b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title {
|
||||
cursor: pointer;
|
||||
+ font-family: var(--vscode-workbench-tabs-font-family, inherit);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label,
|
||||
diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css
|
||||
index e1c147d..76c7b07 100644
|
||||
--- a/src/vs/workbench/browser/parts/panel/media/panelpart.css
|
||||
+++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css
|
||||
@@ -8,6 +8,10 @@
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
+.monaco-workbench .part.panel > .content {
|
||||
+ font-family: var(--vscode-workbench-panel-font-family, inherit);
|
||||
+}
|
||||
+
|
||||
.monaco-workbench .part.panel.bottom .composite.title {
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts
|
||||
index 585bc16..a5d3ff4 100644
|
||||
--- a/src/vs/workbench/browser/parts/panel/panelPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/panel/panelPart.ts
|
||||
@@ -110,6 +110,9 @@ export class PanelPart extends AbstractPaneCompositePart {
|
||||
if (e.affectsConfiguration('workbench.panel.showLabels')) {
|
||||
this.updateCompositeBar(true);
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.bottomPane.experimental.fontFamily')) {
|
||||
+ this.applyPanelFontFamily();
|
||||
+ }
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -126,6 +129,21 @@ export class PanelPart extends AbstractPaneCompositePart {
|
||||
if (this.titleArea) {
|
||||
this.titleArea.style.borderTopColor = this.getColor(PANEL_BORDER) || this.getColor(contrastBorder) || '';
|
||||
}
|
||||
+
|
||||
+ this.applyPanelFontFamily(container);
|
||||
+ }
|
||||
+
|
||||
+ private applyPanelFontFamily(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const family = this.configurationService.getValue<string>('workbench.bottomPane.experimental.fontFamily');
|
||||
+ if (family) {
|
||||
+ target.style.setProperty('--vscode-workbench-panel-font-family', family);
|
||||
+ } else {
|
||||
+ target.style.removeProperty('--vscode-workbench-panel-font-family');
|
||||
+ }
|
||||
}
|
||||
|
||||
protected getCompositeBarOptions(): IPaneCompositeBarOptions {
|
||||
diff --git a/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css b/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css
|
||||
index 7088a97..3a5ff82 100644
|
||||
--- a/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css
|
||||
+++ b/src/vs/workbench/browser/parts/sidebar/media/sidebarpart.css
|
||||
@@ -198,4 +198,8 @@
|
||||
.monaco-workbench .part.sidebar .monaco-custom-toggle {
|
||||
height: calc(var(--vscode-workbench-sidebar-font-size) * 1.539);
|
||||
width: calc(var(--vscode-workbench-sidebar-font-size) * 1.539);
|
||||
-} */
|
||||
\ No newline at end of file
|
||||
+} */
|
||||
+
|
||||
+.monaco-workbench .part.sidebar > .content {
|
||||
+ font-family: var(--vscode-workbench-sidebar-font-family, inherit);
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts
|
||||
index 9b6ae18..322f69b 100644
|
||||
--- a/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/sidebar/sidebarPart.ts
|
||||
@@ -114,6 +114,9 @@ export class SidebarPart extends AbstractPaneCompositePart {
|
||||
if (e.affectsConfiguration(SidebarPart.fontSizeSettingsKey)) {
|
||||
this.applySidebarFontSize();
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.sideBar.experimental.fontFamily')) {
|
||||
+ this.applySidebarFontFamily();
|
||||
+ }
|
||||
}));
|
||||
|
||||
this.registerActions();
|
||||
@@ -155,6 +158,7 @@ export class SidebarPart extends AbstractPaneCompositePart {
|
||||
container.style.outlineColor = this.getColor(SIDE_BAR_DRAG_AND_DROP_BACKGROUND) ?? '';
|
||||
|
||||
this.applySidebarFontSize(container);
|
||||
+ this.applySidebarFontFamily(container);
|
||||
}
|
||||
|
||||
override layout(width: number, height: number, top: number, left: number): void {
|
||||
@@ -297,6 +301,19 @@ export class SidebarPart extends AbstractPaneCompositePart {
|
||||
target.style.setProperty('--vscode-workbench-sidebar-font-size', `${FONT.sidebarSize}px`);
|
||||
}
|
||||
|
||||
+ private applySidebarFontFamily(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const family = this.configurationService.getValue<string>('workbench.sideBar.experimental.fontFamily');
|
||||
+ if (family) {
|
||||
+ target.style.setProperty('--vscode-workbench-sidebar-font-family', family);
|
||||
+ } else {
|
||||
+ target.style.removeProperty('--vscode-workbench-sidebar-font-family');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private registerActions(): void {
|
||||
const that = this;
|
||||
this._register(registerAction2(class extends Action2 {
|
||||
diff --git a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
|
||||
index 7faaf9e..b633ee1 100644
|
||||
--- a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
|
||||
+++ b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
|
||||
@@ -9,6 +9,7 @@
|
||||
width: 100%;
|
||||
height: 22px;
|
||||
font-size: 12px;
|
||||
+ font-family: var(--vscode-workbench-statusbar-font-family, inherit);
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
|
||||
index 4bd53d4..62e78d0 100644
|
||||
--- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
|
||||
@@ -36,6 +36,7 @@ import { StatusBarFocused } from '../../../common/contextkeys.js';
|
||||
import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { IView } from '../../../../base/browser/ui/grid/grid.js';
|
||||
import { isManagedHoverTooltipHTMLElement, isManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
|
||||
+import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
|
||||
export interface IStatusbarEntryContainer extends IDisposable {
|
||||
|
||||
@@ -160,9 +161,16 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IContextMenuService private readonly contextMenuService: IContextMenuService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
+ @IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
) {
|
||||
super(id, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
|
||||
+ this._register(configurationService.onDidChangeConfiguration(e => {
|
||||
+ if (e.affectsConfiguration('workbench.statusBar.experimental.fontFamily')) {
|
||||
+ this.applyStatusBarFontFamily();
|
||||
+ }
|
||||
+ }));
|
||||
+
|
||||
this.viewModel = this._register(new StatusbarViewModel(storageService));
|
||||
this.onDidChangeEntryVisibility = this.viewModel.onDidChangeEntryVisibility;
|
||||
|
||||
@@ -427,9 +435,24 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
|
||||
// Initial status bar entries
|
||||
this.createInitialStatusbarEntries();
|
||||
|
||||
+ this.applyStatusBarFontFamily(this.element);
|
||||
+
|
||||
return this.element;
|
||||
}
|
||||
|
||||
+ private applyStatusBarFontFamily(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+ const family = this.configurationService.getValue<string>('workbench.statusBar.experimental.fontFamily');
|
||||
+ if (family) {
|
||||
+ target.style.setProperty('--vscode-workbench-statusbar-font-family', family);
|
||||
+ } else {
|
||||
+ target.style.removeProperty('--vscode-workbench-statusbar-font-family');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private createInitialStatusbarEntries(): void {
|
||||
|
||||
// Add items in order according to alignment
|
||||
diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts
|
||||
index 3eaad2e..8a9eb0e 100644
|
||||
--- a/src/vs/workbench/browser/workbench.contribution.ts
|
||||
+++ b/src/vs/workbench/browser/workbench.contribution.ts
|
||||
@@ -667,6 +667,44 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
description: localize('workbench.fontFamily', "Controls the font family in the workbench."),
|
||||
'tags': ['experimental']
|
||||
},
|
||||
+ 'workbench.experimental.fontSize': {
|
||||
+ type: 'number',
|
||||
+ default: 13,
|
||||
+ minimum: 6,
|
||||
+ maximum: 32,
|
||||
+ markdownDescription: localize('workbench.fontSize', "Controls the font size in pixels for the workbench."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.sideBar.experimental.fontFamily': {
|
||||
+ type: 'string',
|
||||
+ default: '',
|
||||
+ markdownDescription: localize('sideBarFontFamily', "Controls the font family in the side bar."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.statusBar.experimental.fontFamily': {
|
||||
+ type: 'string',
|
||||
+ default: '',
|
||||
+ markdownDescription: localize('statusBarFontFamily', "Controls the font family in the status bar."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.tabs.experimental.fontFamily': {
|
||||
+ type: 'string',
|
||||
+ default: '',
|
||||
+ markdownDescription: localize('tabsFontFamily', "Controls the font family in editor tabs."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.bottomPane.experimental.fontFamily': {
|
||||
+ type: 'string',
|
||||
+ default: '',
|
||||
+ markdownDescription: localize('bottomPaneFontFamily', "Controls the font family in the bottom panel."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.activityBar.experimental.fontFamily': {
|
||||
+ type: 'string',
|
||||
+ default: '',
|
||||
+ markdownDescription: localize('activityBarFontFamily', "Controls the font family in the activity bar."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
'workbench.settings.editor': {
|
||||
'type': 'string',
|
||||
'enum': ['ui', 'json'],
|
||||
diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts
|
||||
index 7259aff..ee4cbf8 100644
|
||||
--- a/src/vs/workbench/browser/workbench.ts
|
||||
+++ b/src/vs/workbench/browser/workbench.ts
|
||||
@@ -235,9 +235,12 @@ export class Workbench extends Layout {
|
||||
if (e.affectsConfiguration('workbench.fontAliasing')) {
|
||||
this.updateFontAliasing(configurationService);
|
||||
}
|
||||
- else if (e.affectsConfiguration('workbench.experimental.fontFamily')) {
|
||||
+ if (e.affectsConfiguration('workbench.experimental.fontFamily')) {
|
||||
this.updateFontFamily(configurationService);
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.experimental.fontSize')) {
|
||||
+ this.updateFontSize(configurationService);
|
||||
+ }
|
||||
}));
|
||||
|
||||
// Font Info
|
||||
@@ -297,6 +300,33 @@ export class Workbench extends Layout {
|
||||
}
|
||||
}
|
||||
|
||||
+ private fontSize: number | undefined;
|
||||
+ private fontSizeUserSet: boolean | undefined;
|
||||
+ private updateFontSize(configurationService: IConfigurationService) {
|
||||
+ const raw = configurationService.getValue<number>('workbench.experimental.fontSize');
|
||||
+ const size = Math.max(6, Math.min(32, typeof raw === 'number' ? raw : 13));
|
||||
+
|
||||
+ const inspected = configurationService.inspect<number>('workbench.experimental.fontSize');
|
||||
+ const isUserSet = inspected.userValue !== undefined
|
||||
+ || inspected.userLocalValue !== undefined
|
||||
+ || inspected.userRemoteValue !== undefined
|
||||
+ || inspected.workspaceValue !== undefined
|
||||
+ || inspected.workspaceFolderValue !== undefined;
|
||||
+
|
||||
+ if (this.fontSize === size && this.fontSizeUserSet === isUserSet) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ this.fontSize = size;
|
||||
+ this.fontSizeUserSet = isUserSet;
|
||||
+
|
||||
+ if (isUserSet) {
|
||||
+ this.mainContainer.style.setProperty('--vscode-workbench-font-size', `${size}px`);
|
||||
+ } else {
|
||||
+ this.mainContainer.style.removeProperty('--vscode-workbench-font-size');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private fontFamily: string | undefined;
|
||||
private updateFontFamily(configurationService: IConfigurationService) {
|
||||
let family = configurationService.getValue<string>('workbench.experimental.fontFamily');
|
||||
@@ -360,6 +390,7 @@ export class Workbench extends Layout {
|
||||
this.updateFontAliasing(configurationService);
|
||||
|
||||
this.updateFontFamily(configurationService);
|
||||
+ this.updateFontSize(configurationService);
|
||||
|
||||
// Warm up font cache information before building up too many dom elements
|
||||
this.restoreFontInfo(storageService, configurationService);
|
||||
917
patches/feat-workbench-zz-area-font-size-core.patch
Normal file
917
patches/feat-workbench-zz-area-font-size-core.patch
Normal file
@@ -0,0 +1,917 @@
|
||||
diff --git a/src/vs/base/common/font.ts b/src/vs/base/common/font.ts
|
||||
index 2be97d7..8a8d60e 100644
|
||||
--- a/src/vs/base/common/font.ts
|
||||
+++ b/src/vs/base/common/font.ts
|
||||
@@ -1,3 +1,27 @@
|
||||
+/**
|
||||
+ * Inspect a configuration value and return whether it was explicitly set by the user,
|
||||
+ * along with the clamped numeric value.
|
||||
+ */
|
||||
+export function inspectFontSize(
|
||||
+ configurationService: { inspect<T>(key: string): { userValue?: T; userLocalValue?: T; userRemoteValue?: T; workspaceValue?: T; workspaceFolderValue?: T }; getValue<T>(key: string): T },
|
||||
+ key: string,
|
||||
+ defaultSize: number,
|
||||
+ min: number = 6,
|
||||
+ max: number = 32
|
||||
+): { isUserSet: boolean; size: number } {
|
||||
+ const inspected = configurationService.inspect<number>(key);
|
||||
+ const isUserSet = inspected.userValue !== undefined
|
||||
+ || inspected.userLocalValue !== undefined
|
||||
+ || inspected.userRemoteValue !== undefined
|
||||
+ || inspected.workspaceValue !== undefined
|
||||
+ || inspected.workspaceFolderValue !== undefined;
|
||||
+
|
||||
+ const raw = configurationService.getValue<number>(key);
|
||||
+ const size = Math.max(min, Math.min(max, typeof raw === 'number' ? raw : defaultSize));
|
||||
+
|
||||
+ return { isUserSet, size };
|
||||
+}
|
||||
+
|
||||
export const FONT = {
|
||||
sidebarSize: 13,
|
||||
sidebarSize8: 8,
|
||||
@@ -16,8 +40,29 @@ export const FONT = {
|
||||
sidebarSize44: 44,
|
||||
sidebarSize62: 62,
|
||||
sidebarSize72: 72,
|
||||
+
|
||||
+ statusBarSize: 12,
|
||||
+ statusBarSize22: 22,
|
||||
+
|
||||
+ panelSize: 13,
|
||||
+ panelSize22: 22,
|
||||
+
|
||||
+ activityBarSize: 16,
|
||||
+ activityBarSize16: 16,
|
||||
+ activityBarSize24: 24,
|
||||
+ activityBarSize32: 32,
|
||||
+ activityBarSize36: 36,
|
||||
+ activityBarSize48: 48,
|
||||
+
|
||||
+ tabsSize: 13,
|
||||
+ tabsSize22: 22,
|
||||
+ tabsSize35: 35,
|
||||
+ tabsSize38: 38,
|
||||
+ tabsSize80: 80,
|
||||
+ tabsSize120: 120,
|
||||
};
|
||||
|
||||
+// Sidebar coefficients (base 13)
|
||||
const COEFF_8 = 8/13;
|
||||
const COEFF_10 = 10/13;
|
||||
const COEFF_16 = 16/13;
|
||||
@@ -54,3 +99,51 @@ export function updateSidebarSize(size: number): void {
|
||||
FONT.sidebarSize62 = size * COEFF_62;
|
||||
FONT.sidebarSize72 = size * COEFF_72;
|
||||
}
|
||||
+
|
||||
+// Status bar coefficients (base 12)
|
||||
+const SB_COEFF_22 = 22/12;
|
||||
+
|
||||
+export function updateStatusBarSize(size: number): void {
|
||||
+ FONT.statusBarSize = size;
|
||||
+ FONT.statusBarSize22 = size * SB_COEFF_22;
|
||||
+}
|
||||
+
|
||||
+// Panel coefficients (base 13)
|
||||
+const PN_COEFF_22 = 22/13;
|
||||
+
|
||||
+export function updatePanelSize(size: number): void {
|
||||
+ FONT.panelSize = size;
|
||||
+ FONT.panelSize22 = size * PN_COEFF_22;
|
||||
+}
|
||||
+
|
||||
+// Activity bar coefficients (base 16)
|
||||
+const AB_COEFF_16 = 16/16;
|
||||
+const AB_COEFF_24 = 24/16;
|
||||
+const AB_COEFF_32 = 32/16;
|
||||
+const AB_COEFF_36 = 36/16;
|
||||
+const AB_COEFF_48 = 48/16;
|
||||
+
|
||||
+export function updateActivityBarSize(size: number): void {
|
||||
+ FONT.activityBarSize = size;
|
||||
+ FONT.activityBarSize16 = size * AB_COEFF_16;
|
||||
+ FONT.activityBarSize24 = size * AB_COEFF_24;
|
||||
+ FONT.activityBarSize32 = size * AB_COEFF_32;
|
||||
+ FONT.activityBarSize36 = size * AB_COEFF_36;
|
||||
+ FONT.activityBarSize48 = size * AB_COEFF_48;
|
||||
+}
|
||||
+
|
||||
+// Tabs coefficients (base 13)
|
||||
+const TB_COEFF_22 = 22/13;
|
||||
+const TB_COEFF_35 = 35/13;
|
||||
+const TB_COEFF_38 = 38/13;
|
||||
+const TB_COEFF_80 = 80/13;
|
||||
+const TB_COEFF_120 = 120/13;
|
||||
+
|
||||
+export function updateTabsSize(size: number): void {
|
||||
+ FONT.tabsSize = size;
|
||||
+ FONT.tabsSize22 = size * TB_COEFF_22;
|
||||
+ FONT.tabsSize35 = size * TB_COEFF_35;
|
||||
+ FONT.tabsSize38 = size * TB_COEFF_38;
|
||||
+ FONT.tabsSize80 = size * TB_COEFF_80;
|
||||
+ FONT.tabsSize120 = size * TB_COEFF_120;
|
||||
+}
|
||||
diff --git a/src/vs/base/test/common/font.test.ts b/src/vs/base/test/common/font.test.ts
|
||||
new file mode 100644
|
||||
index 0000000..dcde0e7
|
||||
--- /dev/null
|
||||
+++ b/src/vs/base/test/common/font.test.ts
|
||||
@@ -0,0 +1,482 @@
|
||||
+/*---------------------------------------------------------------------------------------------
|
||||
+ * Copyright (c) VSCodium. All rights reserved.
|
||||
+ * Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
+ *--------------------------------------------------------------------------------------------*/
|
||||
+
|
||||
+import assert from 'assert';
|
||||
+import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../test/common/utils.js';
|
||||
+import { FONT, updateSidebarSize, updateStatusBarSize, updatePanelSize, updateActivityBarSize, updateTabsSize } from '../../common/font.js';
|
||||
+
|
||||
+/**
|
||||
+ * Test file for src/vs/base/common/font.ts
|
||||
+ *
|
||||
+ * Tests all update*Size() functions for:
|
||||
+ * - Default values match upstream VS Code hardcoded constants
|
||||
+ * - Proportional scaling preserves ratios at non-default sizes
|
||||
+ * - Boundary values (minimum=6, maximum=32) produce positive values
|
||||
+ * - Reset to default restores original values
|
||||
+ * - Non-divisible sizes produce consistent coefficient-based output
|
||||
+ * - Cross-area updates do not mutate unrelated fields
|
||||
+ */
|
||||
+
|
||||
+const EPSILON = 1e-9;
|
||||
+
|
||||
+/** Assert two numbers are equal within floating-point tolerance */
|
||||
+function assertClose(actual: number, expected: number, message?: string): void {
|
||||
+ const diff = Math.abs(actual - expected);
|
||||
+ assert.ok(diff < EPSILON, `${message ?? ''} expected ${expected}, got ${actual} (diff: ${diff})`);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Snapshot all FONT fields to detect unintended mutations.
|
||||
+ * Returns a plain object copy of every enumerable property.
|
||||
+ */
|
||||
+function snapshotFont(): Record<string, number> {
|
||||
+ const snap: Record<string, number> = {};
|
||||
+ for (const key of Object.keys(FONT)) {
|
||||
+ snap[key] = (FONT as Record<string, number>)[key];
|
||||
+ }
|
||||
+ return snap;
|
||||
+}
|
||||
+
|
||||
+/** Assert that specific fields in FONT have not changed from a snapshot */
|
||||
+function assertFieldsUnchanged(snapshot: Record<string, number>, prefix: string, message: string): void {
|
||||
+ for (const key of Object.keys(snapshot)) {
|
||||
+ if (key.startsWith(prefix)) {
|
||||
+ assertClose((FONT as Record<string, number>)[key], snapshot[key], `${message}: ${key}`);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+suite('FONT - Sidebar Size', () => {
|
||||
+
|
||||
+ ensureNoDisposablesAreLeakedInTestSuite();
|
||||
+
|
||||
+ // Capture defaults before any test mutates them
|
||||
+ const DEFAULTS = snapshotFont();
|
||||
+
|
||||
+ teardown(() => {
|
||||
+ // Reset after each test
|
||||
+ updateSidebarSize(13);
|
||||
+ });
|
||||
+
|
||||
+ test('defaults match upstream VS Code constants', () => {
|
||||
+ assert.strictEqual(FONT.sidebarSize, 13);
|
||||
+ assert.strictEqual(FONT.sidebarSize8, 8);
|
||||
+ assert.strictEqual(FONT.sidebarSize10, 10);
|
||||
+ assert.strictEqual(FONT.sidebarSize16, 16);
|
||||
+ assert.strictEqual(FONT.sidebarSize17, 17);
|
||||
+ assert.strictEqual(FONT.sidebarSize18, 18);
|
||||
+ assert.strictEqual(FONT.sidebarSize20, 20);
|
||||
+ assert.strictEqual(FONT.sidebarSize22, 22);
|
||||
+ assert.strictEqual(FONT.sidebarSize23, 23);
|
||||
+ assert.strictEqual(FONT.sidebarSize24, 24);
|
||||
+ assert.strictEqual(FONT.sidebarSize26, 26);
|
||||
+ assert.strictEqual(FONT.sidebarSize28, 28);
|
||||
+ assert.strictEqual(FONT.sidebarSize34, 34);
|
||||
+ assert.strictEqual(FONT.sidebarSize39, 39);
|
||||
+ assert.strictEqual(FONT.sidebarSize44, 44);
|
||||
+ assert.strictEqual(FONT.sidebarSize62, 62);
|
||||
+ assert.strictEqual(FONT.sidebarSize72, 72);
|
||||
+ });
|
||||
+
|
||||
+ test('proportional scaling preserves ratios at 2x', () => {
|
||||
+ updateSidebarSize(26); // 2x default
|
||||
+ assert.strictEqual(FONT.sidebarSize, 26);
|
||||
+ assert.strictEqual(FONT.sidebarSize8, 16);
|
||||
+ assert.strictEqual(FONT.sidebarSize22, 44);
|
||||
+ assert.strictEqual(FONT.sidebarSize44, 88);
|
||||
+ assert.strictEqual(FONT.sidebarSize72, 144);
|
||||
+ });
|
||||
+
|
||||
+ test('non-divisible size produces consistent coefficient-based values', () => {
|
||||
+ updateSidebarSize(7);
|
||||
+ assertClose(FONT.sidebarSize22, 7 * (22 / 13));
|
||||
+ assertClose(FONT.sidebarSize44, 7 * (44 / 13));
|
||||
+ assertClose(FONT.sidebarSize72, 7 * (72 / 13));
|
||||
+ });
|
||||
+
|
||||
+ test('another non-divisible size (31)', () => {
|
||||
+ updateSidebarSize(31);
|
||||
+ assertClose(FONT.sidebarSize22, 31 * (22 / 13));
|
||||
+ assertClose(FONT.sidebarSize44, 31 * (44 / 13));
|
||||
+ });
|
||||
+
|
||||
+ test('minimum value (6) produces positive values', () => {
|
||||
+ updateSidebarSize(6);
|
||||
+ assert.strictEqual(FONT.sidebarSize, 6);
|
||||
+ assert.ok(FONT.sidebarSize8 > 0, 'sidebarSize8 must be positive');
|
||||
+ assert.ok(FONT.sidebarSize10 > 0, 'sidebarSize10 must be positive');
|
||||
+ assert.ok(FONT.sidebarSize22 > 0, 'sidebarSize22 must be positive');
|
||||
+ assert.ok(FONT.sidebarSize72 > 0, 'sidebarSize72 must be positive');
|
||||
+ });
|
||||
+
|
||||
+ test('maximum value (32) produces reasonable values', () => {
|
||||
+ updateSidebarSize(32);
|
||||
+ assert.strictEqual(FONT.sidebarSize, 32);
|
||||
+ assert.ok(FONT.sidebarSize22 > 40, 'row height should scale up');
|
||||
+ assert.ok(FONT.sidebarSize22 < 80, 'row height should not be extreme');
|
||||
+ });
|
||||
+
|
||||
+ test('reset to default restores all values', () => {
|
||||
+ updateSidebarSize(20);
|
||||
+ assert.notStrictEqual(FONT.sidebarSize22, DEFAULTS.sidebarSize22);
|
||||
+ updateSidebarSize(13);
|
||||
+ assertFieldsUnchanged(DEFAULTS, 'sidebar', 'after reset');
|
||||
+ });
|
||||
+
|
||||
+ test('multiple updates in sequence are idempotent at same value', () => {
|
||||
+ updateSidebarSize(18);
|
||||
+ const snap = snapshotFont();
|
||||
+ updateSidebarSize(18);
|
||||
+ assertFieldsUnchanged(snap, 'sidebar', 'idempotent');
|
||||
+ });
|
||||
+});
|
||||
+
|
||||
+suite('FONT - Status Bar Size', () => {
|
||||
+
|
||||
+ ensureNoDisposablesAreLeakedInTestSuite();
|
||||
+
|
||||
+ teardown(() => {
|
||||
+ updateStatusBarSize(12);
|
||||
+ });
|
||||
+
|
||||
+ test('defaults match upstream VS Code status bar constants', () => {
|
||||
+ assert.strictEqual(FONT.statusBarSize, 12);
|
||||
+ assert.strictEqual(FONT.statusBarSize22, 22); // StatusbarPart.HEIGHT
|
||||
+ });
|
||||
+
|
||||
+ test('proportional scaling at 2x', () => {
|
||||
+ updateStatusBarSize(24);
|
||||
+ assert.strictEqual(FONT.statusBarSize, 24);
|
||||
+ assert.strictEqual(FONT.statusBarSize22, 44);
|
||||
+ });
|
||||
+
|
||||
+ test('non-divisible size (7)', () => {
|
||||
+ updateStatusBarSize(7);
|
||||
+ assertClose(FONT.statusBarSize22, 7 * (22 / 12));
|
||||
+ });
|
||||
+
|
||||
+ test('minimum value (6) produces positive height', () => {
|
||||
+ updateStatusBarSize(6);
|
||||
+ assert.strictEqual(FONT.statusBarSize, 6);
|
||||
+ assert.ok(FONT.statusBarSize22 > 0, 'height must be positive');
|
||||
+ assertClose(FONT.statusBarSize22, 6 * (22 / 12));
|
||||
+ });
|
||||
+
|
||||
+ test('maximum value (32) produces reasonable height', () => {
|
||||
+ updateStatusBarSize(32);
|
||||
+ assertClose(FONT.statusBarSize22, 32 * (22 / 12));
|
||||
+ assert.ok(FONT.statusBarSize22 > 50, 'height should scale up');
|
||||
+ assert.ok(FONT.statusBarSize22 < 70, 'height should not be extreme');
|
||||
+ });
|
||||
+
|
||||
+ test('reset to default restores values', () => {
|
||||
+ updateStatusBarSize(20);
|
||||
+ updateStatusBarSize(12);
|
||||
+ assert.strictEqual(FONT.statusBarSize, 12);
|
||||
+ assert.strictEqual(FONT.statusBarSize22, 22);
|
||||
+ });
|
||||
+});
|
||||
+
|
||||
+suite('FONT - Panel Size', () => {
|
||||
+
|
||||
+ ensureNoDisposablesAreLeakedInTestSuite();
|
||||
+
|
||||
+ teardown(() => {
|
||||
+ updatePanelSize(13);
|
||||
+ });
|
||||
+
|
||||
+ test('defaults match sidebar defaults (same base size)', () => {
|
||||
+ assert.strictEqual(FONT.panelSize, 13);
|
||||
+ assert.strictEqual(FONT.panelSize22, 22);
|
||||
+ });
|
||||
+
|
||||
+ test('panel and sidebar can have independent sizes', () => {
|
||||
+ updatePanelSize(18);
|
||||
+ assert.strictEqual(FONT.panelSize, 18);
|
||||
+ assert.notStrictEqual(FONT.panelSize22, 22);
|
||||
+ // Sidebar unchanged
|
||||
+ assert.strictEqual(FONT.sidebarSize, 13);
|
||||
+ assert.strictEqual(FONT.sidebarSize22, 22);
|
||||
+ });
|
||||
+
|
||||
+ test('proportional scaling at 2x', () => {
|
||||
+ updatePanelSize(26);
|
||||
+ assert.strictEqual(FONT.panelSize22, 44);
|
||||
+ });
|
||||
+
|
||||
+ test('non-divisible size (7)', () => {
|
||||
+ updatePanelSize(7);
|
||||
+ assertClose(FONT.panelSize22, 7 * (22 / 13));
|
||||
+ });
|
||||
+
|
||||
+ test('minimum value (6)', () => {
|
||||
+ updatePanelSize(6);
|
||||
+ assert.ok(FONT.panelSize22 > 0, 'row height must be positive');
|
||||
+ assert.ok(FONT.panelSize22 >= 10, 'row height at minimum should be usable');
|
||||
+ });
|
||||
+
|
||||
+ test('maximum value (32)', () => {
|
||||
+ updatePanelSize(32);
|
||||
+ assert.ok(FONT.panelSize22 > 50, 'row height should scale up');
|
||||
+ });
|
||||
+
|
||||
+ test('reset to default restores values', () => {
|
||||
+ updatePanelSize(20);
|
||||
+ updatePanelSize(13);
|
||||
+ assert.strictEqual(FONT.panelSize, 13);
|
||||
+ assert.strictEqual(FONT.panelSize22, 22);
|
||||
+ });
|
||||
+});
|
||||
+
|
||||
+suite('FONT - Activity Bar Size', () => {
|
||||
+
|
||||
+ ensureNoDisposablesAreLeakedInTestSuite();
|
||||
+
|
||||
+ teardown(() => {
|
||||
+ updateActivityBarSize(16);
|
||||
+ });
|
||||
+
|
||||
+ test('defaults match upstream VS Code activity bar constants', () => {
|
||||
+ assert.strictEqual(FONT.activityBarSize, 16);
|
||||
+ assert.strictEqual(FONT.activityBarSize16, 16); // COMPACT_ICON_SIZE
|
||||
+ assert.strictEqual(FONT.activityBarSize24, 24); // ICON_SIZE
|
||||
+ assert.strictEqual(FONT.activityBarSize32, 32); // COMPACT_ACTION_HEIGHT
|
||||
+ assert.strictEqual(FONT.activityBarSize36, 36); // COMPACT_ACTIVITYBAR_WIDTH
|
||||
+ assert.strictEqual(FONT.activityBarSize48, 48); // ACTION_HEIGHT / ACTIVITYBAR_WIDTH
|
||||
+ });
|
||||
+
|
||||
+ test('proportional scaling at 2x', () => {
|
||||
+ updateActivityBarSize(32);
|
||||
+ assert.strictEqual(FONT.activityBarSize, 32);
|
||||
+ assert.strictEqual(FONT.activityBarSize16, 32); // compact icon = base size
|
||||
+ assert.strictEqual(FONT.activityBarSize24, 48);
|
||||
+ assert.strictEqual(FONT.activityBarSize32, 64);
|
||||
+ assert.strictEqual(FONT.activityBarSize36, 72);
|
||||
+ assert.strictEqual(FONT.activityBarSize48, 96);
|
||||
+ });
|
||||
+
|
||||
+ test('compact constants scale correctly', () => {
|
||||
+ updateActivityBarSize(20);
|
||||
+ // Compact icon size = base size * (16/16) = 20
|
||||
+ assertClose(FONT.activityBarSize16, 20 * (16 / 16));
|
||||
+ // Compact width = base * (36/16) = 45
|
||||
+ assertClose(FONT.activityBarSize36, 20 * (36 / 16));
|
||||
+ // Compact action height = base * (32/16) = 40
|
||||
+ assertClose(FONT.activityBarSize32, 20 * (32 / 16));
|
||||
+ });
|
||||
+
|
||||
+ test('non-divisible size (7)', () => {
|
||||
+ updateActivityBarSize(7);
|
||||
+ assertClose(FONT.activityBarSize24, 7 * (24 / 16));
|
||||
+ assertClose(FONT.activityBarSize48, 7 * (48 / 16));
|
||||
+ assertClose(FONT.activityBarSize36, 7 * (36 / 16));
|
||||
+ });
|
||||
+
|
||||
+ test('minimum value (6) produces positive values', () => {
|
||||
+ updateActivityBarSize(6);
|
||||
+ assert.strictEqual(FONT.activityBarSize, 6);
|
||||
+ assert.ok(FONT.activityBarSize16 > 0, 'compact icon size must be positive');
|
||||
+ assert.ok(FONT.activityBarSize24 > 0, 'icon size must be positive');
|
||||
+ assert.ok(FONT.activityBarSize36 > 0, 'compact width must be positive');
|
||||
+ assert.ok(FONT.activityBarSize48 > 0, 'action height must be positive');
|
||||
+ });
|
||||
+
|
||||
+ test('maximum value (32) produces reasonable values', () => {
|
||||
+ updateActivityBarSize(32);
|
||||
+ assert.strictEqual(FONT.activityBarSize48, 96);
|
||||
+ assert.ok(FONT.activityBarSize48 <= 100, 'action height should be bounded');
|
||||
+ });
|
||||
+
|
||||
+ test('reset to default restores values', () => {
|
||||
+ updateActivityBarSize(24);
|
||||
+ updateActivityBarSize(16);
|
||||
+ assert.strictEqual(FONT.activityBarSize, 16);
|
||||
+ assert.strictEqual(FONT.activityBarSize16, 16);
|
||||
+ assert.strictEqual(FONT.activityBarSize24, 24);
|
||||
+ assert.strictEqual(FONT.activityBarSize32, 32);
|
||||
+ assert.strictEqual(FONT.activityBarSize36, 36);
|
||||
+ assert.strictEqual(FONT.activityBarSize48, 48);
|
||||
+ });
|
||||
+});
|
||||
+
|
||||
+suite('FONT - Tabs Size', () => {
|
||||
+
|
||||
+ ensureNoDisposablesAreLeakedInTestSuite();
|
||||
+
|
||||
+ teardown(() => {
|
||||
+ updateTabsSize(13);
|
||||
+ });
|
||||
+
|
||||
+ test('defaults match upstream VS Code tab constants', () => {
|
||||
+ assert.strictEqual(FONT.tabsSize, 13);
|
||||
+ assert.strictEqual(FONT.tabsSize22, 22); // EDITOR_TAB_HEIGHT compact
|
||||
+ assert.strictEqual(FONT.tabsSize35, 35); // EDITOR_TAB_HEIGHT normal
|
||||
+ assert.strictEqual(FONT.tabsSize38, 38); // TAB_WIDTH compact
|
||||
+ assert.strictEqual(FONT.tabsSize80, 80); // TAB_WIDTH shrink
|
||||
+ assert.strictEqual(FONT.tabsSize120, 120); // TAB_WIDTH fit
|
||||
+ });
|
||||
+
|
||||
+ test('proportional scaling preserves tab height/width ratios at 2x', () => {
|
||||
+ updateTabsSize(26);
|
||||
+ assert.strictEqual(FONT.tabsSize, 26);
|
||||
+ assert.strictEqual(FONT.tabsSize22, 44);
|
||||
+ assert.strictEqual(FONT.tabsSize35, 70);
|
||||
+ assert.strictEqual(FONT.tabsSize38, 76);
|
||||
+ assert.strictEqual(FONT.tabsSize80, 160);
|
||||
+ assert.strictEqual(FONT.tabsSize120, 240);
|
||||
+ });
|
||||
+
|
||||
+ test('non-divisible size (7)', () => {
|
||||
+ updateTabsSize(7);
|
||||
+ assertClose(FONT.tabsSize22, 7 * (22 / 13));
|
||||
+ assertClose(FONT.tabsSize35, 7 * (35 / 13));
|
||||
+ assertClose(FONT.tabsSize80, 7 * (80 / 13));
|
||||
+ assertClose(FONT.tabsSize120, 7 * (120 / 13));
|
||||
+ });
|
||||
+
|
||||
+ test('minimum value (6) produces usable tab dimensions', () => {
|
||||
+ updateTabsSize(6);
|
||||
+ assert.strictEqual(FONT.tabsSize, 6);
|
||||
+ assert.ok(FONT.tabsSize35 > 10, 'normal tab height must be clickable');
|
||||
+ assert.ok(FONT.tabsSize22 > 8, 'compact tab height must be usable');
|
||||
+ assert.ok(FONT.tabsSize38 > 0, 'compact tab width must be positive');
|
||||
+ assert.ok(FONT.tabsSize80 > 0, 'shrink tab width must be positive');
|
||||
+ });
|
||||
+
|
||||
+ test('maximum value (32) produces reasonable tab dimensions', () => {
|
||||
+ updateTabsSize(32);
|
||||
+ assert.ok(FONT.tabsSize35 > 80, 'normal tab height should scale up');
|
||||
+ assert.ok(FONT.tabsSize35 < 100, 'normal tab height should be bounded');
|
||||
+ });
|
||||
+
|
||||
+ test('reset to default restores all values', () => {
|
||||
+ updateTabsSize(20);
|
||||
+ updateTabsSize(13);
|
||||
+ assert.strictEqual(FONT.tabsSize, 13);
|
||||
+ assert.strictEqual(FONT.tabsSize22, 22);
|
||||
+ assert.strictEqual(FONT.tabsSize35, 35);
|
||||
+ assert.strictEqual(FONT.tabsSize38, 38);
|
||||
+ assert.strictEqual(FONT.tabsSize80, 80);
|
||||
+ assert.strictEqual(FONT.tabsSize120, 120);
|
||||
+ });
|
||||
+});
|
||||
+
|
||||
+suite('FONT - Cross-area independence', () => {
|
||||
+
|
||||
+ ensureNoDisposablesAreLeakedInTestSuite();
|
||||
+
|
||||
+ teardown(() => {
|
||||
+ updateSidebarSize(13);
|
||||
+ updateStatusBarSize(12);
|
||||
+ updatePanelSize(13);
|
||||
+ updateActivityBarSize(16);
|
||||
+ updateTabsSize(13);
|
||||
+ });
|
||||
+
|
||||
+ test('updating sidebar does not affect any other area (full derived field check)', () => {
|
||||
+ const before = snapshotFont();
|
||||
+ updateSidebarSize(20);
|
||||
+
|
||||
+ // All non-sidebar fields must be unchanged
|
||||
+ assertFieldsUnchanged(before, 'statusBar', 'after sidebar update');
|
||||
+ assertFieldsUnchanged(before, 'panel', 'after sidebar update');
|
||||
+ assertFieldsUnchanged(before, 'activityBar', 'after sidebar update');
|
||||
+ assertFieldsUnchanged(before, 'tabs', 'after sidebar update');
|
||||
+ });
|
||||
+
|
||||
+ test('updating statusBar does not affect any other area', () => {
|
||||
+ const before = snapshotFont();
|
||||
+ updateStatusBarSize(20);
|
||||
+
|
||||
+ assertFieldsUnchanged(before, 'sidebar', 'after statusBar update');
|
||||
+ assertFieldsUnchanged(before, 'panel', 'after statusBar update');
|
||||
+ assertFieldsUnchanged(before, 'activityBar', 'after statusBar update');
|
||||
+ assertFieldsUnchanged(before, 'tabs', 'after statusBar update');
|
||||
+ });
|
||||
+
|
||||
+ test('updating panel does not affect any other area', () => {
|
||||
+ const before = snapshotFont();
|
||||
+ updatePanelSize(20);
|
||||
+
|
||||
+ assertFieldsUnchanged(before, 'sidebar', 'after panel update');
|
||||
+ assertFieldsUnchanged(before, 'statusBar', 'after panel update');
|
||||
+ assertFieldsUnchanged(before, 'activityBar', 'after panel update');
|
||||
+ assertFieldsUnchanged(before, 'tabs', 'after panel update');
|
||||
+ });
|
||||
+
|
||||
+ test('updating activityBar does not affect any other area', () => {
|
||||
+ const before = snapshotFont();
|
||||
+ updateActivityBarSize(20);
|
||||
+
|
||||
+ assertFieldsUnchanged(before, 'sidebar', 'after activityBar update');
|
||||
+ assertFieldsUnchanged(before, 'statusBar', 'after activityBar update');
|
||||
+ assertFieldsUnchanged(before, 'panel', 'after activityBar update');
|
||||
+ assertFieldsUnchanged(before, 'tabs', 'after activityBar update');
|
||||
+ });
|
||||
+
|
||||
+ test('updating tabs does not affect any other area', () => {
|
||||
+ const before = snapshotFont();
|
||||
+ updateTabsSize(20);
|
||||
+
|
||||
+ assertFieldsUnchanged(before, 'sidebar', 'after tabs update');
|
||||
+ assertFieldsUnchanged(before, 'statusBar', 'after tabs update');
|
||||
+ assertFieldsUnchanged(before, 'panel', 'after tabs update');
|
||||
+ assertFieldsUnchanged(before, 'activityBar', 'after tabs update');
|
||||
+ });
|
||||
+
|
||||
+ test('all areas set to same value produce different derived values due to different coefficients', () => {
|
||||
+ const commonSize = 18;
|
||||
+ updateSidebarSize(commonSize);
|
||||
+ updateStatusBarSize(commonSize);
|
||||
+ updatePanelSize(commonSize);
|
||||
+ updateActivityBarSize(commonSize);
|
||||
+ updateTabsSize(commonSize);
|
||||
+
|
||||
+ assert.strictEqual(FONT.sidebarSize, commonSize);
|
||||
+ assert.strictEqual(FONT.statusBarSize, commonSize);
|
||||
+ assert.strictEqual(FONT.panelSize, commonSize);
|
||||
+ assert.strictEqual(FONT.activityBarSize, commonSize);
|
||||
+ assert.strictEqual(FONT.tabsSize, commonSize);
|
||||
+
|
||||
+ // sidebarSize22 = 18 * (22/13), statusBarSize22 = 18 * (22/12)
|
||||
+ // Different coefficients → different results
|
||||
+ assert.notStrictEqual(FONT.sidebarSize22, FONT.statusBarSize22,
|
||||
+ 'same base size should produce different derived values due to different coefficients');
|
||||
+ });
|
||||
+
|
||||
+ test('sequential updates across all areas and full reset', () => {
|
||||
+ updateSidebarSize(8);
|
||||
+ updateStatusBarSize(10);
|
||||
+ updatePanelSize(15);
|
||||
+ updateActivityBarSize(20);
|
||||
+ updateTabsSize(25);
|
||||
+
|
||||
+ // Verify all set correctly
|
||||
+ assert.strictEqual(FONT.sidebarSize, 8);
|
||||
+ assert.strictEqual(FONT.statusBarSize, 10);
|
||||
+ assert.strictEqual(FONT.panelSize, 15);
|
||||
+ assert.strictEqual(FONT.activityBarSize, 20);
|
||||
+ assert.strictEqual(FONT.tabsSize, 25);
|
||||
+
|
||||
+ // Reset all
|
||||
+ updateSidebarSize(13);
|
||||
+ updateStatusBarSize(12);
|
||||
+ updatePanelSize(13);
|
||||
+ updateActivityBarSize(16);
|
||||
+ updateTabsSize(13);
|
||||
+
|
||||
+ // All defaults restored
|
||||
+ assert.strictEqual(FONT.sidebarSize, 13);
|
||||
+ assert.strictEqual(FONT.sidebarSize22, 22);
|
||||
+ assert.strictEqual(FONT.statusBarSize, 12);
|
||||
+ assert.strictEqual(FONT.statusBarSize22, 22);
|
||||
+ assert.strictEqual(FONT.panelSize, 13);
|
||||
+ assert.strictEqual(FONT.panelSize22, 22);
|
||||
+ assert.strictEqual(FONT.activityBarSize, 16);
|
||||
+ assert.strictEqual(FONT.activityBarSize48, 48);
|
||||
+ assert.strictEqual(FONT.tabsSize, 13);
|
||||
+ assert.strictEqual(FONT.tabsSize35, 35);
|
||||
+ });
|
||||
+});
|
||||
diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
|
||||
index cbd14af..83153fe 100644
|
||||
--- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
|
||||
@@ -38,11 +38,11 @@ import { IExtensionService } from '../../../services/extensions/common/extension
|
||||
import { IWorkbenchEnvironmentService } from '../../../services/environment/common/environmentService.js';
|
||||
import { IViewsService } from '../../../services/views/common/viewsService.js';
|
||||
import { SwitchCompositeViewAction } from '../compositeBarActions.js';
|
||||
-import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
+import { FONT, inspectFontSize, updateActivityBarSize } from '../../../../base/common/font.js';
|
||||
|
||||
export class ActivitybarPart extends Part {
|
||||
|
||||
- static readonly ACTION_HEIGHT = 48;
|
||||
+ static get ACTION_HEIGHT() { return FONT.activityBarSize48; }
|
||||
|
||||
static readonly pinnedViewContainersKey = 'workbench.activity.pinnedViewlets2';
|
||||
static readonly placeholderViewContainersKey = 'workbench.activity.placeholderViewlets';
|
||||
@@ -74,6 +74,9 @@ export class ActivitybarPart extends Part {
|
||||
if (e.affectsConfiguration('workbench.activityBar.experimental.fontFamily')) {
|
||||
this.applyActivityBarFontFamily();
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.activityBar.experimental.fontSize')) {
|
||||
+ this.applyActivityBarFontSize();
|
||||
+ }
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -111,15 +114,34 @@ export class ActivitybarPart extends Part {
|
||||
this.element = parent;
|
||||
this.content = append(this.element, $('.content'));
|
||||
|
||||
+ // Apply font settings before show() so composite bar uses correct sizes
|
||||
+ this.applyActivityBarFontFamily(parent);
|
||||
+ this.applyActivityBarFontSize(parent);
|
||||
+
|
||||
if (this.layoutService.isVisible(Parts.ACTIVITYBAR_PART)) {
|
||||
this.show();
|
||||
}
|
||||
|
||||
- this.applyActivityBarFontFamily(parent);
|
||||
-
|
||||
return this.content;
|
||||
}
|
||||
|
||||
+ private applyActivityBarFontSize(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.activityBar.experimental.fontSize', 16);
|
||||
+
|
||||
+ if (isUserSet) {
|
||||
+ updateActivityBarSize(size);
|
||||
+ target.style.setProperty('--vscode-workbench-activitybar-font-size', `${size}px`);
|
||||
+ } else {
|
||||
+ updateActivityBarSize(16);
|
||||
+ target.style.removeProperty('--vscode-workbench-activitybar-font-size');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private applyActivityBarFontFamily(container?: HTMLElement): void {
|
||||
const target = container ?? this.getContainer();
|
||||
if (!target) {
|
||||
diff --git a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
|
||||
index 7cd25d0..680dc73 100644
|
||||
--- a/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
|
||||
+++ b/src/vs/workbench/browser/parts/activitybar/media/activitybarpart.css
|
||||
@@ -7,6 +7,7 @@
|
||||
width: 48px;
|
||||
height: 100%;
|
||||
font-family: var(--vscode-workbench-activitybar-font-family, inherit);
|
||||
+ font-size: var(--vscode-workbench-activitybar-font-size, var(--vscode-workbench-font-size, 16px));
|
||||
}
|
||||
|
||||
.monaco-workbench .activitybar.bordered::before {
|
||||
diff --git a/src/vs/workbench/browser/parts/panel/media/panelpart.css b/src/vs/workbench/browser/parts/panel/media/panelpart.css
|
||||
index 76c7b07..6faf068 100644
|
||||
--- a/src/vs/workbench/browser/parts/panel/media/panelpart.css
|
||||
+++ b/src/vs/workbench/browser/parts/panel/media/panelpart.css
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
.monaco-workbench .part.panel > .content {
|
||||
font-family: var(--vscode-workbench-panel-font-family, inherit);
|
||||
+ font-size: var(--vscode-workbench-panel-font-size, var(--vscode-workbench-font-size, 13px));
|
||||
}
|
||||
|
||||
.monaco-workbench .part.panel.bottom .composite.title {
|
||||
diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts
|
||||
index a5d3ff4..b9b240d 100644
|
||||
--- a/src/vs/workbench/browser/parts/panel/panelPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/panel/panelPart.ts
|
||||
@@ -31,6 +31,7 @@ import { getContextMenuActions } from '../../../../platform/actions/browser/menu
|
||||
import { IPaneCompositeBarOptions } from '../paneCompositeBar.js';
|
||||
import { IHoverService } from '../../../../platform/hover/browser/hover.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
+import { FONT, inspectFontSize, updatePanelSize } from '../../../../base/common/font.js';
|
||||
|
||||
export class PanelPart extends AbstractPaneCompositePart {
|
||||
|
||||
@@ -113,6 +114,9 @@ export class PanelPart extends AbstractPaneCompositePart {
|
||||
if (e.affectsConfiguration('workbench.bottomPane.experimental.fontFamily')) {
|
||||
this.applyPanelFontFamily();
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.bottomPane.experimental.fontSize')) {
|
||||
+ this.applyPanelFontSize();
|
||||
+ }
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -131,6 +135,24 @@ export class PanelPart extends AbstractPaneCompositePart {
|
||||
}
|
||||
|
||||
this.applyPanelFontFamily(container);
|
||||
+ this.applyPanelFontSize(container);
|
||||
+ }
|
||||
+
|
||||
+ private applyPanelFontSize(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.bottomPane.experimental.fontSize', 13);
|
||||
+
|
||||
+ if (isUserSet) {
|
||||
+ updatePanelSize(size);
|
||||
+ target.style.setProperty('--vscode-workbench-panel-font-size', `${size}px`);
|
||||
+ } else {
|
||||
+ updatePanelSize(13);
|
||||
+ target.style.removeProperty('--vscode-workbench-panel-font-size');
|
||||
+ }
|
||||
}
|
||||
|
||||
private applyPanelFontFamily(container?: HTMLElement): void {
|
||||
diff --git a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
|
||||
index b633ee1..7621d4e 100644
|
||||
--- a/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
|
||||
+++ b/src/vs/workbench/browser/parts/statusbar/media/statusbarpart.css
|
||||
@@ -7,8 +7,8 @@
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
width: 100%;
|
||||
- height: 22px;
|
||||
- font-size: 12px;
|
||||
+ height: var(--vscode-workbench-statusbar-height, 22px);
|
||||
+ font-size: var(--vscode-workbench-statusbar-font-size, var(--vscode-workbench-font-size, 12px));
|
||||
font-family: var(--vscode-workbench-statusbar-font-family, inherit);
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
.monaco-workbench .part.statusbar > .items-container > .statusbar-item {
|
||||
display: inline-block;
|
||||
- line-height: 22px;
|
||||
+ line-height: var(--vscode-workbench-statusbar-height, 22px);
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
max-width: 40vw;
|
||||
diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
|
||||
index 62e78d0..d5dc64a 100644
|
||||
--- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
|
||||
+++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts
|
||||
@@ -37,6 +37,7 @@ import { Emitter, Event } from '../../../../base/common/event.js';
|
||||
import { IView } from '../../../../base/browser/ui/grid/grid.js';
|
||||
import { isManagedHoverTooltipHTMLElement, isManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
+import { FONT, inspectFontSize, updateStatusBarSize } from '../../../../base/common/font.js';
|
||||
|
||||
export interface IStatusbarEntryContainer extends IDisposable {
|
||||
|
||||
@@ -119,14 +120,14 @@ interface IPendingStatusbarEntry {
|
||||
|
||||
class StatusbarPart extends Part implements IStatusbarEntryContainer {
|
||||
|
||||
- static readonly HEIGHT = 22;
|
||||
+ static get HEIGHT() { return FONT.statusBarSize22; }
|
||||
|
||||
//#region IView
|
||||
|
||||
readonly minimumWidth: number = 0;
|
||||
readonly maximumWidth: number = Number.POSITIVE_INFINITY;
|
||||
- readonly minimumHeight: number = StatusbarPart.HEIGHT;
|
||||
- readonly maximumHeight: number = StatusbarPart.HEIGHT;
|
||||
+ get minimumHeight(): number { return FONT.statusBarSize22; }
|
||||
+ get maximumHeight(): number { return FONT.statusBarSize22; }
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -169,6 +170,9 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
|
||||
if (e.affectsConfiguration('workbench.statusBar.experimental.fontFamily')) {
|
||||
this.applyStatusBarFontFamily();
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.statusBar.experimental.fontSize')) {
|
||||
+ this.applyStatusBarFontSize();
|
||||
+ }
|
||||
}));
|
||||
|
||||
this.viewModel = this._register(new StatusbarViewModel(storageService));
|
||||
@@ -436,10 +440,33 @@ class StatusbarPart extends Part implements IStatusbarEntryContainer {
|
||||
this.createInitialStatusbarEntries();
|
||||
|
||||
this.applyStatusBarFontFamily(this.element);
|
||||
+ this.applyStatusBarFontSize(this.element);
|
||||
|
||||
return this.element;
|
||||
}
|
||||
|
||||
+ private applyStatusBarFontSize(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.getContainer();
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.statusBar.experimental.fontSize', 12);
|
||||
+
|
||||
+ if (isUserSet) {
|
||||
+ updateStatusBarSize(size);
|
||||
+ target.style.setProperty('--vscode-workbench-statusbar-font-size', `${size}px`);
|
||||
+ target.style.setProperty('--vscode-workbench-statusbar-height', `${FONT.statusBarSize22}px`);
|
||||
+ } else {
|
||||
+ updateStatusBarSize(12);
|
||||
+ target.style.removeProperty('--vscode-workbench-statusbar-font-size');
|
||||
+ target.style.removeProperty('--vscode-workbench-statusbar-height');
|
||||
+ }
|
||||
+
|
||||
+ // Notify grid layout that height constraints changed
|
||||
+ this._onDidChange.fire(undefined);
|
||||
+ }
|
||||
+
|
||||
private applyStatusBarFontFamily(container?: HTMLElement): void {
|
||||
const target = container ?? this.getContainer();
|
||||
if (!target) {
|
||||
@@ -761,7 +788,7 @@ export class AuxiliaryStatusbarPart extends StatusbarPart implements IAuxiliaryS
|
||||
|
||||
private static COUNTER = 1;
|
||||
|
||||
- readonly height = StatusbarPart.HEIGHT;
|
||||
+ get height() { return StatusbarPart.HEIGHT; }
|
||||
|
||||
constructor(
|
||||
readonly container: HTMLElement,
|
||||
diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts
|
||||
index 8a9eb0e..5bb0959 100644
|
||||
--- a/src/vs/workbench/browser/workbench.contribution.ts
|
||||
+++ b/src/vs/workbench/browser/workbench.contribution.ts
|
||||
@@ -705,6 +705,38 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
markdownDescription: localize('activityBarFontFamily', "Controls the font family in the activity bar."),
|
||||
'tags': ['accessibility', 'experimental']
|
||||
},
|
||||
+ 'workbench.statusBar.experimental.fontSize': {
|
||||
+ type: 'number',
|
||||
+ default: 12,
|
||||
+ minimum: 6,
|
||||
+ maximum: 32,
|
||||
+ markdownDescription: localize('statusBarFontSize', "Controls the font size in pixels for the status bar."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.bottomPane.experimental.fontSize': {
|
||||
+ type: 'number',
|
||||
+ default: 13,
|
||||
+ minimum: 6,
|
||||
+ maximum: 32,
|
||||
+ markdownDescription: localize('bottomPaneFontSize', "Controls the font size in pixels for the bottom panel."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.activityBar.experimental.fontSize': {
|
||||
+ type: 'number',
|
||||
+ default: 16,
|
||||
+ minimum: 6,
|
||||
+ maximum: 32,
|
||||
+ markdownDescription: localize('activityBarFontSize', "Controls the font size in pixels for the activity bar."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
+ 'workbench.tabs.experimental.fontSize': {
|
||||
+ type: 'number',
|
||||
+ default: 13,
|
||||
+ minimum: 6,
|
||||
+ maximum: 32,
|
||||
+ markdownDescription: localize('tabsFontSize', "Controls the font size in pixels for editor tabs."),
|
||||
+ 'tags': ['accessibility', 'experimental']
|
||||
+ },
|
||||
'workbench.settings.editor': {
|
||||
'type': 'string',
|
||||
'enum': ['ui', 'json'],
|
||||
diff --git a/src/vs/workbench/browser/workbench.ts b/src/vs/workbench/browser/workbench.ts
|
||||
index ee4cbf8..4d7a787 100644
|
||||
--- a/src/vs/workbench/browser/workbench.ts
|
||||
+++ b/src/vs/workbench/browser/workbench.ts
|
||||
@@ -7,6 +7,7 @@ import './style.js';
|
||||
import { runWhenWindowIdle } from '../../base/browser/dom.js';
|
||||
import { Event, Emitter, setGlobalLeakWarningThreshold } from '../../base/common/event.js';
|
||||
import { RunOnceScheduler, timeout } from '../../base/common/async.js';
|
||||
+import { inspectFontSize } from '../../base/common/font.js';
|
||||
import { isFirefox, isSafari, isChrome } from '../../base/browser/browser.js';
|
||||
import { mark } from '../../base/common/performance.js';
|
||||
import { onUnexpectedError, setUnexpectedErrorHandler } from '../../base/common/errors.js';
|
||||
@@ -303,15 +304,7 @@ export class Workbench extends Layout {
|
||||
private fontSize: number | undefined;
|
||||
private fontSizeUserSet: boolean | undefined;
|
||||
private updateFontSize(configurationService: IConfigurationService) {
|
||||
- const raw = configurationService.getValue<number>('workbench.experimental.fontSize');
|
||||
- const size = Math.max(6, Math.min(32, typeof raw === 'number' ? raw : 13));
|
||||
-
|
||||
- const inspected = configurationService.inspect<number>('workbench.experimental.fontSize');
|
||||
- const isUserSet = inspected.userValue !== undefined
|
||||
- || inspected.userLocalValue !== undefined
|
||||
- || inspected.userRemoteValue !== undefined
|
||||
- || inspected.workspaceValue !== undefined
|
||||
- || inspected.workspaceFolderValue !== undefined;
|
||||
+ const { isUserSet, size } = inspectFontSize(configurationService, 'workbench.experimental.fontSize', 13);
|
||||
|
||||
if (this.fontSize === size && this.fontSizeUserSet === isUserSet) {
|
||||
return;
|
||||
223
patches/feat-workbench-zz-area-font-size-tabs.patch
Normal file
223
patches/feat-workbench-zz-area-font-size-tabs.patch
Normal file
@@ -0,0 +1,223 @@
|
||||
diff --git a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
|
||||
index a946cb7..4db07a2 100644
|
||||
--- a/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
|
||||
+++ b/src/vs/workbench/browser/parts/editor/editorTabsControl.ts
|
||||
@@ -47,6 +47,7 @@ import { IBaseActionViewItemOptions } from '../../../../base/browser/ui/actionba
|
||||
import { MarkdownString } from '../../../../base/common/htmlContent.js';
|
||||
import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js';
|
||||
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
|
||||
+import { FONT, inspectFontSize, updateTabsSize } from '../../../../base/common/font.js';
|
||||
import { applyDragImage } from '../../../../base/browser/ui/dnd/dnd.js';
|
||||
|
||||
export class EditorCommandsContextActionRunner extends ActionRunner {
|
||||
@@ -100,10 +101,12 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
|
||||
protected readonly groupTransfer = LocalSelectionTransfer.getInstance<DraggedEditorGroupIdentifier>();
|
||||
protected readonly treeItemsTransfer = LocalSelectionTransfer.getInstance<DraggedTreeItemsIdentifier>();
|
||||
|
||||
- private static readonly EDITOR_TAB_HEIGHT = {
|
||||
- normal: 35 as const,
|
||||
- compact: 22 as const
|
||||
- };
|
||||
+ private static get EDITOR_TAB_HEIGHT() {
|
||||
+ return {
|
||||
+ normal: FONT.tabsSize35,
|
||||
+ compact: FONT.tabsSize22
|
||||
+ };
|
||||
+ }
|
||||
|
||||
protected editorActionsToolbarContainer: HTMLElement | undefined;
|
||||
private editorActionsToolbar: WorkbenchToolBar | undefined;
|
||||
@@ -153,6 +156,11 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
|
||||
if (e.affectsConfiguration('workbench.tabs.experimental.fontFamily')) {
|
||||
this.applyTabsFontFamily();
|
||||
}
|
||||
+ if (e.affectsConfiguration('workbench.tabs.experimental.fontSize')) {
|
||||
+ this.applyTabsFontSize();
|
||||
+ this.updateTabHeight();
|
||||
+ this.groupView.relayout();
|
||||
+ }
|
||||
}));
|
||||
|
||||
// Context Keys
|
||||
@@ -176,11 +184,37 @@ export abstract class EditorTabsControl extends Themable implements IEditorTabsC
|
||||
}
|
||||
|
||||
protected create(parent: HTMLElement): HTMLElement {
|
||||
+ this.applyTabsFontSize(parent);
|
||||
this.updateTabHeight();
|
||||
this.applyTabsFontFamily(parent);
|
||||
return parent;
|
||||
}
|
||||
|
||||
+ private applyTabsFontSize(container?: HTMLElement): void {
|
||||
+ const target = container ?? this.parent;
|
||||
+ if (!target) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ const { isUserSet, size } = inspectFontSize(this.configurationService, 'workbench.tabs.experimental.fontSize', 13);
|
||||
+
|
||||
+ if (isUserSet) {
|
||||
+ updateTabsSize(size);
|
||||
+ target.style.setProperty('--vscode-workbench-tabs-font-size', `${size}px`);
|
||||
+ target.style.setProperty('--vscode-workbench-tabs-compact-height', `${FONT.tabsSize22}px`);
|
||||
+ target.style.setProperty('--vscode-workbench-tabs-sticky-compact-width', `${FONT.tabsSize38}px`);
|
||||
+ target.style.setProperty('--vscode-workbench-tabs-sticky-shrink-width', `${FONT.tabsSize80}px`);
|
||||
+ target.style.setProperty('--vscode-workbench-tabs-fit-width', `${FONT.tabsSize120}px`);
|
||||
+ } else {
|
||||
+ updateTabsSize(13);
|
||||
+ target.style.removeProperty('--vscode-workbench-tabs-font-size');
|
||||
+ target.style.removeProperty('--vscode-workbench-tabs-compact-height');
|
||||
+ target.style.removeProperty('--vscode-workbench-tabs-sticky-compact-width');
|
||||
+ target.style.removeProperty('--vscode-workbench-tabs-sticky-shrink-width');
|
||||
+ target.style.removeProperty('--vscode-workbench-tabs-fit-width');
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private applyTabsFontFamily(container?: HTMLElement): void {
|
||||
const target = container ?? this.parent;
|
||||
if (!target) {
|
||||
diff --git a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
|
||||
index e9e0b2b..fc1bebe 100644
|
||||
--- a/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
|
||||
+++ b/src/vs/workbench/browser/parts/editor/media/editortabscontrol.css
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .title-label a,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab .tab-label a {
|
||||
- font-size: 13px;
|
||||
+ font-size: var(--vscode-workbench-tabs-font-size, var(--vscode-workbench-font-size, 13px));
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .monaco-icon-label::before,
|
||||
diff --git a/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css b/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css
|
||||
index a24f761..8c72d17 100644
|
||||
--- a/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css
|
||||
+++ b/src/vs/workbench/browser/parts/editor/media/editortitlecontrol.css
|
||||
@@ -7,23 +7,23 @@
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control {
|
||||
flex: 1 100%;
|
||||
- height: 22px;
|
||||
+ height: var(--vscode-workbench-tabs-compact-height, 22px);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-icon-label {
|
||||
- height: 22px;
|
||||
- line-height: 22px;
|
||||
+ height: var(--vscode-workbench-tabs-compact-height, 22px);
|
||||
+ line-height: var(--vscode-workbench-tabs-compact-height, 22px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-icon-label::before {
|
||||
- height: 22px; /* tweak the icon size of the editor labels when icons are enabled */
|
||||
+ height: var(--vscode-workbench-tabs-compact-height, 22px); /* tweak the icon size of the editor labels when icons are enabled */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .outline-element-icon {
|
||||
padding-right: 3px;
|
||||
- height: 22px; /* tweak the icon size of the editor labels when icons are enabled */
|
||||
- line-height: 22px;
|
||||
+ height: var(--vscode-workbench-tabs-compact-height, 22px); /* tweak the icon size of the editor labels when icons are enabled */
|
||||
+ line-height: var(--vscode-workbench-tabs-compact-height, 22px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-breadcrumb-item {
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .breadcrumbs-below-tabs .breadcrumbs-control .monaco-breadcrumb-item::before {
|
||||
width: 16px;
|
||||
- height: 22px;
|
||||
+ height: var(--vscode-workbench-tabs-compact-height, 22px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
diff --git a/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css b/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css
|
||||
index 924d9b3..58efc4d 100644
|
||||
--- a/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css
|
||||
+++ b/src/vs/workbench/browser/parts/editor/media/multieditortabscontrol.css
|
||||
@@ -160,7 +160,7 @@
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
|
||||
- width: 120px;
|
||||
+ width: var(--vscode-workbench-tabs-fit-width, 120px);
|
||||
min-width: fit-content;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -183,7 +183,7 @@
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink {
|
||||
- min-width: 80px;
|
||||
+ min-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
|
||||
flex-basis: 0; /* all tabs are even */
|
||||
flex-grow: 1; /* all tabs grow even */
|
||||
max-width: fit-content;
|
||||
@@ -210,9 +210,9 @@
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.sticky-compact {
|
||||
|
||||
/** Sticky compact tabs have a fixed width of 38px */
|
||||
- width: 38px;
|
||||
- min-width: 38px;
|
||||
- max-width: 38px;
|
||||
+ width: var(--vscode-workbench-tabs-sticky-compact-width, 38px);
|
||||
+ min-width: var(--vscode-workbench-tabs-sticky-compact-width, 38px);
|
||||
+ max-width: var(--vscode-workbench-tabs-sticky-compact-width, 38px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky-shrink,
|
||||
@@ -220,9 +220,9 @@
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.sticky-shrink {
|
||||
|
||||
/** Sticky shrink tabs have a fixed width of 80px */
|
||||
- width: 80px;
|
||||
- min-width: 80px;
|
||||
- max-width: 80px;
|
||||
+ width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
|
||||
+ min-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
|
||||
+ max-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky-compact,
|
||||
@@ -257,7 +257,7 @@
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.tab-actions-left,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fixed.tab-actions-left {
|
||||
- min-width: 80px; /* make more room for close button when it shows to the left */
|
||||
+ min-width: var(--vscode-workbench-tabs-sticky-shrink-width, 80px); /* make more room for close button when it shows to the left */
|
||||
padding-right: 5px; /* we need less room when sizing is shrink/fixed */
|
||||
}
|
||||
|
||||
diff --git a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts
|
||||
index b0befd9..ef06bcc 100644
|
||||
--- a/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts
|
||||
+++ b/src/vs/workbench/browser/parts/editor/multiEditorTabsControl.ts
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import './media/multieditortabscontrol.css';
|
||||
+import { FONT } from '../../../../base/common/font.js';
|
||||
import { isLinux, isMacintosh, isWindows } from '../../../../base/common/platform.js';
|
||||
import { shorten } from '../../../../base/common/labels.js';
|
||||
import { EditorResourceAccessor, Verbosity, IEditorPartOptions, SideBySideEditor, DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities, IUntypedEditorInput, preventEditorClose, EditorCloseMethod, EditorsOrder, IToolbarActions } from '../../../common/editor.js';
|
||||
@@ -94,11 +95,13 @@ export class MultiEditorTabsControl extends EditorTabsControl {
|
||||
large: 10 as const
|
||||
};
|
||||
|
||||
- private static readonly TAB_WIDTH = {
|
||||
- compact: 38 as const,
|
||||
- shrink: 80 as const,
|
||||
- fit: 120 as const
|
||||
- };
|
||||
+ private static get TAB_WIDTH() {
|
||||
+ return {
|
||||
+ compact: FONT.tabsSize38,
|
||||
+ shrink: FONT.tabsSize80,
|
||||
+ fit: FONT.tabsSize120
|
||||
+ };
|
||||
+ }
|
||||
|
||||
private static readonly DRAG_OVER_OPEN_TAB_THRESHOLD = 1500;
|
||||
|
||||
Reference in New Issue
Block a user