Path: blob/main/src/vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { createStyleSheet } from '../../../../base/browser/domStylesheets.js';6import { Event } from '../../../../base/common/event.js';7import { Disposable, DisposableStore, toDisposable } from '../../../../base/common/lifecycle.js';8import { clamp } from '../../../../base/common/numbers.js';9import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';10import { IWorkbenchContribution } from '../../../common/contributions.js';11import { AccessibilityWorkbenchSettingId, ViewDimUnfocusedOpacityProperties } from './accessibilityConfiguration.js';1213export class UnfocusedViewDimmingContribution extends Disposable implements IWorkbenchContribution {14private _styleElement?: HTMLStyleElement;15private _styleElementDisposables: DisposableStore | undefined = undefined;1617constructor(18@IConfigurationService configurationService: IConfigurationService,19) {20super();2122this._register(toDisposable(() => this._removeStyleElement()));2324this._register(Event.runAndSubscribe(configurationService.onDidChangeConfiguration, e => {25if (e && !e.affectsConfiguration(AccessibilityWorkbenchSettingId.DimUnfocusedEnabled) && !e.affectsConfiguration(AccessibilityWorkbenchSettingId.DimUnfocusedOpacity)) {26return;27}2829let cssTextContent = '';3031const enabled = ensureBoolean(configurationService.getValue(AccessibilityWorkbenchSettingId.DimUnfocusedEnabled), false);32if (enabled) {33const opacity = clamp(34ensureNumber(configurationService.getValue(AccessibilityWorkbenchSettingId.DimUnfocusedOpacity), ViewDimUnfocusedOpacityProperties.Default),35ViewDimUnfocusedOpacityProperties.Minimum,36ViewDimUnfocusedOpacityProperties.Maximum37);3839if (opacity !== 1) {40// These filter rules are more specific than may be expected as the `filter`41// rule can cause problems if it's used inside the element like on editor hovers42const rules = new Set<string>();43const filterRule = `filter: opacity(${opacity});`;44// Terminal tabs45rules.add(`.monaco-workbench .pane-body.integrated-terminal:not(:focus-within) .tabs-container { ${filterRule} }`);46// Terminals47rules.add(`.monaco-workbench .pane-body.integrated-terminal .terminal-wrapper:not(:focus-within) { ${filterRule} }`);48// Text editors49rules.add(`.monaco-workbench .editor-instance:not(:focus-within) .monaco-editor { ${filterRule} }`);50// Breadcrumbs51rules.add(`.monaco-workbench .editor-instance:not(:focus-within) .breadcrumbs-below-tabs { ${filterRule} }`);52// Terminal editors53rules.add(`.monaco-workbench .editor-instance:not(:focus-within) .terminal-wrapper { ${filterRule} }`);54// Settings editor55rules.add(`.monaco-workbench .editor-instance:not(:focus-within) .settings-editor { ${filterRule} }`);56// Keybindings editor57rules.add(`.monaco-workbench .editor-instance:not(:focus-within) .keybindings-editor { ${filterRule} }`);58// Editor placeholder (error case)59rules.add(`.monaco-workbench .editor-instance:not(:focus-within) .monaco-editor-pane-placeholder { ${filterRule} }`);60// Welcome editor61rules.add(`.monaco-workbench .editor-instance:not(:focus-within) .gettingStartedContainer { ${filterRule} }`);62cssTextContent = [...rules].join('\n');63}6465}6667if (cssTextContent.length === 0) {68this._removeStyleElement();69} else {70this._getStyleElement().textContent = cssTextContent;71}72}));73}7475private _getStyleElement(): HTMLStyleElement {76if (!this._styleElement) {77this._styleElementDisposables = new DisposableStore();78this._styleElement = createStyleSheet(undefined, undefined, this._styleElementDisposables);79this._styleElement.className = 'accessibilityUnfocusedViewOpacity';80}81return this._styleElement;82}8384private _removeStyleElement(): void {85this._styleElementDisposables?.dispose();86this._styleElementDisposables = undefined;87this._styleElement = undefined;88}89}909192function ensureBoolean(value: unknown, defaultValue: boolean): boolean {93return typeof value === 'boolean' ? value : defaultValue;94}9596function ensureNumber(value: unknown, defaultValue: number): number {97return typeof value === 'number' ? value : defaultValue;98}99100101