Skip to content

Commit dd17e82

Browse files
authored
standalone theme service: improve detection, toggle (microsoft#154357)
* standalone theme service: clean up os theme detection * toggle to matching high contrast
1 parent e5f5a16 commit dd17e82

File tree

2 files changed

+43
-39
lines changed

2 files changed

+43
-39
lines changed

src/vs/editor/standalone/browser/standaloneThemeService.ts

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import { Registry } from 'vs/platform/registry/common/platform';
1717
import { asCssVariableName, ColorIdentifier, Extensions, IColorRegistry } from 'vs/platform/theme/common/colorRegistry';
1818
import { Extensions as ThemingExtensions, ICssStyleCollector, IFileIconTheme, IProductIconTheme, IThemingRegistry, ITokenStyle } from 'vs/platform/theme/common/themeService';
1919
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
20-
import { ColorScheme, isDark } from 'vs/platform/theme/common/theme';
20+
import { ColorScheme, isDark, isHighContrast } from 'vs/platform/theme/common/theme';
2121
import { getIconsStyleSheet, UnthemedProductIconTheme } from 'vs/platform/theme/browser/iconsStyleSheet';
2222

23-
const VS_THEME_NAME = 'vs';
24-
const VS_DARK_THEME_NAME = 'vs-dark';
25-
const HC_BLACK_THEME_NAME = 'hc-black';
26-
const HC_LIGHT_THEME_NAME = 'hc-light';
23+
export const VS_LIGHT_THEME_NAME = 'vs';
24+
export const VS_DARK_THEME_NAME = 'vs-dark';
25+
export const HC_BLACK_THEME_NAME = 'hc-black';
26+
export const HC_LIGHT_THEME_NAME = 'hc-light';
2727

2828
const colorRegistry = Registry.as<IColorRegistry>(Extensions.ColorContribution);
2929
const themingRegistry = Registry.as<IThemingRegistry>(ThemingExtensions.ThemingContribution);
@@ -118,7 +118,7 @@ class StandaloneTheme implements IStandaloneTheme {
118118

119119
public get type(): ColorScheme {
120120
switch (this.base) {
121-
case VS_THEME_NAME: return ColorScheme.LIGHT;
121+
case VS_LIGHT_THEME_NAME: return ColorScheme.LIGHT;
122122
case HC_BLACK_THEME_NAME: return ColorScheme.HIGH_CONTRAST_DARK;
123123
case HC_LIGHT_THEME_NAME: return ColorScheme.HIGH_CONTRAST_LIGHT;
124124
default: return ColorScheme.DARK;
@@ -182,7 +182,7 @@ class StandaloneTheme implements IStandaloneTheme {
182182

183183
function isBuiltinTheme(themeName: string): themeName is BuiltinTheme {
184184
return (
185-
themeName === VS_THEME_NAME
185+
themeName === VS_LIGHT_THEME_NAME
186186
|| themeName === VS_DARK_THEME_NAME
187187
|| themeName === HC_BLACK_THEME_NAME
188188
|| themeName === HC_LIGHT_THEME_NAME
@@ -191,7 +191,7 @@ function isBuiltinTheme(themeName: string): themeName is BuiltinTheme {
191191

192192
function getBuiltinRules(builtinTheme: BuiltinTheme): IStandaloneThemeData {
193193
switch (builtinTheme) {
194-
case VS_THEME_NAME:
194+
case VS_LIGHT_THEME_NAME:
195195
return vs;
196196
case VS_DARK_THEME_NAME:
197197
return vs_dark;
@@ -229,7 +229,6 @@ export class StandaloneThemeService extends Disposable implements IStandaloneThe
229229
private _globalStyleElement: HTMLStyleElement | null;
230230
private _styleElements: HTMLStyleElement[];
231231
private _colorMapOverride: Color[] | null;
232-
private _desiredTheme!: IStandaloneTheme;
233232
private _theme!: IStandaloneTheme;
234233

235234
private _builtInProductIconTheme = new UnthemedProductIconTheme();
@@ -240,7 +239,7 @@ export class StandaloneThemeService extends Disposable implements IStandaloneThe
240239
this._autoDetectHighContrast = true;
241240

242241
this._knownThemes = new Map<string, StandaloneTheme>();
243-
this._knownThemes.set(VS_THEME_NAME, newBuiltInTheme(VS_THEME_NAME));
242+
this._knownThemes.set(VS_LIGHT_THEME_NAME, newBuiltInTheme(VS_LIGHT_THEME_NAME));
244243
this._knownThemes.set(VS_DARK_THEME_NAME, newBuiltInTheme(VS_DARK_THEME_NAME));
245244
this._knownThemes.set(HC_BLACK_THEME_NAME, newBuiltInTheme(HC_BLACK_THEME_NAME));
246245
this._knownThemes.set(HC_LIGHT_THEME_NAME, newBuiltInTheme(HC_LIGHT_THEME_NAME));
@@ -253,15 +252,16 @@ export class StandaloneThemeService extends Disposable implements IStandaloneThe
253252
this._globalStyleElement = null;
254253
this._styleElements = [];
255254
this._colorMapOverride = null;
256-
this.setTheme(VS_THEME_NAME);
255+
this.setTheme(VS_LIGHT_THEME_NAME);
256+
this._onOSSchemeChanged();
257257

258258
iconsStyleSheet.onDidChange(() => {
259259
this._codiconCSS = iconsStyleSheet.getCSS();
260260
this._updateCSS();
261261
});
262262

263263
addMatchMediaChangeListener('(forced-colors: active)', () => {
264-
this._updateActualTheme();
264+
this._onOSSchemeChanged();
265265
});
266266
}
267267

@@ -331,41 +331,43 @@ export class StandaloneThemeService extends Disposable implements IStandaloneThe
331331
}
332332

333333
public setTheme(themeName: string): void {
334-
let theme: StandaloneTheme;
334+
let theme: StandaloneTheme | undefined;
335335
if (this._knownThemes.has(themeName)) {
336-
theme = this._knownThemes.get(themeName)!;
336+
theme = this._knownThemes.get(themeName);
337337
} else {
338-
theme = this._knownThemes.get(VS_THEME_NAME)!;
338+
theme = this._knownThemes.get(VS_LIGHT_THEME_NAME);
339339
}
340-
this._desiredTheme = theme;
341-
this._updateActualTheme();
340+
this._updateActualTheme(theme);
342341
}
343342

344-
private getHighContrastTheme() {
345-
if (isDark(this._desiredTheme.type)) {
346-
return HC_BLACK_THEME_NAME;
347-
} else {
348-
return HC_LIGHT_THEME_NAME;
349-
}
350-
}
351-
352-
private _updateActualTheme(): void {
353-
const theme = (
354-
this._autoDetectHighContrast && window.matchMedia(`(forced-colors: active)`).matches
355-
? this._knownThemes.get(this.getHighContrastTheme())!
356-
: this._desiredTheme
357-
);
358-
if (this._theme === theme) {
343+
private _updateActualTheme(desiredTheme: IStandaloneTheme | undefined): void {
344+
if (!desiredTheme || this._theme === desiredTheme) {
359345
// Nothing to do
360346
return;
361347
}
362-
this._theme = theme;
348+
this._theme = desiredTheme;
363349
this._updateThemeOrColorMap();
364350
}
365351

352+
private _onOSSchemeChanged() {
353+
if (this._autoDetectHighContrast) {
354+
const wantsHighContrast = window.matchMedia(`(forced-colors: active)`).matches;
355+
if (wantsHighContrast !== isHighContrast(this._theme.type)) {
356+
// switch to high contrast or non-high contrast but stick to dark or light
357+
let newThemeName;
358+
if (isDark(this._theme.type)) {
359+
newThemeName = wantsHighContrast ? HC_BLACK_THEME_NAME : VS_DARK_THEME_NAME;
360+
} else {
361+
newThemeName = wantsHighContrast ? HC_LIGHT_THEME_NAME : VS_LIGHT_THEME_NAME;
362+
}
363+
this._updateActualTheme(this._knownThemes.get(newThemeName));
364+
}
365+
}
366+
}
367+
366368
public setAutoDetectHighContrast(autoDetectHighContrast: boolean): void {
367369
this._autoDetectHighContrast = autoDetectHighContrast;
368-
this._updateActualTheme();
370+
this._onOSSchemeChanged();
369371
}
370372

371373
private _updateThemeOrColorMap(): void {

src/vs/editor/standalone/browser/toggleHighContrast/toggleHighContrast.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
77
import { EditorAction, ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions';
88
import { IStandaloneThemeService } from 'vs/editor/standalone/common/standaloneTheme';
99
import { ToggleHighContrastNLS } from 'vs/editor/common/standaloneStrings';
10-
import { isHighContrast } from 'vs/platform/theme/common/theme';
10+
import { isDark, isHighContrast } from 'vs/platform/theme/common/theme';
11+
import { HC_BLACK_THEME_NAME, HC_LIGHT_THEME_NAME, VS_DARK_THEME_NAME, VS_LIGHT_THEME_NAME } from 'vs/editor/standalone/browser/standaloneThemeService';
1112

1213
class ToggleHighContrast extends EditorAction {
1314

@@ -25,13 +26,14 @@ class ToggleHighContrast extends EditorAction {
2526

2627
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
2728
const standaloneThemeService = accessor.get(IStandaloneThemeService);
28-
if (isHighContrast(standaloneThemeService.getColorTheme().type)) {
29+
const currentTheme = standaloneThemeService.getColorTheme();
30+
if (isHighContrast(currentTheme.type)) {
2931
// We must toggle back to the integrator's theme
30-
standaloneThemeService.setTheme(this._originalThemeName || 'vs');
32+
standaloneThemeService.setTheme(this._originalThemeName || (isDark(currentTheme.type) ? VS_DARK_THEME_NAME : VS_LIGHT_THEME_NAME));
3133
this._originalThemeName = null;
3234
} else {
33-
this._originalThemeName = standaloneThemeService.getColorTheme().themeName;
34-
standaloneThemeService.setTheme('hc-black');
35+
standaloneThemeService.setTheme(isDark(currentTheme.type) ? HC_BLACK_THEME_NAME : HC_LIGHT_THEME_NAME);
36+
this._originalThemeName = currentTheme.themeName;
3537
}
3638
}
3739
}

0 commit comments

Comments
 (0)