mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-15 07:28:05 +00:00
Merge pull request #295164 from microsoft/mrleemurray/driving-black-cod
Add support for reduced transparency in accessibility settings
This commit is contained in:
@@ -682,3 +682,167 @@
|
||||
opacity: 1;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
/* ============================================================================================
|
||||
* Reduced Transparency - disable backdrop-filter blur and color-mix transparency effects
|
||||
* for improved rendering performance. Controlled by workbench.reduceTransparency setting.
|
||||
* ============================================================================================ */
|
||||
|
||||
/* Reset blur variables to none */
|
||||
.monaco-workbench.monaco-reduce-transparency {
|
||||
--backdrop-blur-sm: none;
|
||||
--backdrop-blur-md: none;
|
||||
--backdrop-blur-lg: none;
|
||||
}
|
||||
|
||||
/* Quick Input (Command Palette) */
|
||||
.monaco-workbench.monaco-reduce-transparency .quick-input-widget {
|
||||
background-color: var(--vscode-quickInput-background) !important;
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
/* Notifications */
|
||||
.monaco-workbench.monaco-reduce-transparency .notification-toast-container {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
background: var(--vscode-notifications-background) !important;
|
||||
}
|
||||
|
||||
.monaco-workbench.monaco-reduce-transparency .notifications-center {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
background: var(--vscode-notifications-background) !important;
|
||||
}
|
||||
|
||||
/* Context Menu / Action Widget */
|
||||
.monaco-workbench.monaco-reduce-transparency .action-widget {
|
||||
background: var(--vscode-menu-background) !important;
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
/* Suggest Widget */
|
||||
.monaco-workbench.monaco-reduce-transparency .monaco-editor .suggest-widget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
background: var(--vscode-editorSuggestWidget-background) !important;
|
||||
}
|
||||
|
||||
/* Find Widget */
|
||||
.monaco-workbench.monaco-reduce-transparency .monaco-editor .find-widget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
.monaco-workbench.monaco-reduce-transparency .inline-chat-gutter-menu {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
/* Dialog */
|
||||
.monaco-workbench.monaco-reduce-transparency .monaco-dialog-box {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
background: var(--vscode-editor-background) !important;
|
||||
}
|
||||
|
||||
/* Peek View */
|
||||
.monaco-workbench.monaco-reduce-transparency .monaco-editor .peekview-widget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
background: var(--vscode-peekViewEditor-background) !important;
|
||||
}
|
||||
|
||||
/* Hover */
|
||||
.monaco-reduce-transparency .monaco-hover {
|
||||
background-color: var(--vscode-editorHoverWidget-background) !important;
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
.monaco-reduce-transparency .monaco-hover.workbench-hover,
|
||||
.monaco-reduce-transparency .workbench-hover {
|
||||
background-color: var(--vscode-editorHoverWidget-background) !important;
|
||||
-webkit-backdrop-filter: none !important;
|
||||
backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
/* Keybinding Widget */
|
||||
.monaco-workbench.monaco-reduce-transparency .defineKeybindingWidget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
/* Chat Editor Overlay */
|
||||
.monaco-workbench.monaco-reduce-transparency .chat-editor-overlay-widget,
|
||||
.monaco-workbench.monaco-reduce-transparency .chat-diff-change-content-widget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
/* Debug Toolbar */
|
||||
.monaco-workbench.monaco-reduce-transparency .debug-toolbar {
|
||||
-webkit-backdrop-filter: none !important;
|
||||
backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
.monaco-workbench.monaco-reduce-transparency .debug-hover-widget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
/* Parameter Hints */
|
||||
.monaco-workbench.monaco-reduce-transparency .monaco-editor .parameter-hints-widget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
background: var(--vscode-editorWidget-background) !important;
|
||||
}
|
||||
|
||||
/* Sticky Scroll */
|
||||
.monaco-workbench.monaco-reduce-transparency .monaco-editor .sticky-widget {
|
||||
-webkit-backdrop-filter: none !important;
|
||||
backdrop-filter: none !important;
|
||||
background: var(--vscode-editor-background) !important;
|
||||
}
|
||||
|
||||
.monaco-workbench.monaco-reduce-transparency .monaco-editor .sticky-widget .sticky-widget-lines {
|
||||
-webkit-backdrop-filter: none !important;
|
||||
backdrop-filter: none !important;
|
||||
background: var(--vscode-editor-background) !important;
|
||||
}
|
||||
|
||||
/* Rename Box */
|
||||
.monaco-reduce-transparency .monaco-editor .rename-box.preview {
|
||||
-webkit-backdrop-filter: none !important;
|
||||
backdrop-filter: none !important;
|
||||
}
|
||||
|
||||
/* Notebook */
|
||||
.monaco-workbench.monaco-reduce-transparency .notebookOverlay .monaco-list-row .cell-title-toolbar {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
/* Command Center */
|
||||
.monaco-workbench.monaco-reduce-transparency .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center {
|
||||
background: var(--vscode-commandCenter-background) !important;
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
}
|
||||
|
||||
.monaco-workbench.monaco-reduce-transparency .part.titlebar > .titlebar-container > .titlebar-center > .window-title > .command-center .action-item.command-center-center:hover {
|
||||
background: var(--vscode-commandCenter-activeBackground) !important;
|
||||
}
|
||||
|
||||
/* Breadcrumbs */
|
||||
.monaco-workbench.monaco-reduce-transparency .breadcrumbs-picker-widget {
|
||||
-webkit-backdrop-filter: none;
|
||||
backdrop-filter: none;
|
||||
background: var(--vscode-breadcrumbPicker-background) !important;
|
||||
}
|
||||
|
||||
/* Quick Input filter input */
|
||||
.monaco-workbench.monaco-reduce-transparency .quick-input-widget .quick-input-filter .monaco-inputbox {
|
||||
background: var(--vscode-input-background) !important;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ export class AccessibilityService extends Disposable implements IAccessibilitySe
|
||||
protected _systemMotionReduced: boolean;
|
||||
protected readonly _onDidChangeReducedMotion = this._register(new Emitter<void>());
|
||||
|
||||
protected _configTransparencyReduced: 'auto' | 'on' | 'off';
|
||||
protected _systemTransparencyReduced: boolean;
|
||||
protected readonly _onDidChangeReducedTransparency = this._register(new Emitter<void>());
|
||||
|
||||
private _linkUnderlinesEnabled: boolean;
|
||||
protected readonly _onDidChangeLinkUnderline = this._register(new Emitter<void>());
|
||||
|
||||
@@ -45,6 +49,10 @@ export class AccessibilityService extends Disposable implements IAccessibilitySe
|
||||
this._configMotionReduced = this._configurationService.getValue('workbench.reduceMotion');
|
||||
this._onDidChangeReducedMotion.fire();
|
||||
}
|
||||
if (e.affectsConfiguration('workbench.reduceTransparency')) {
|
||||
this._configTransparencyReduced = this._configurationService.getValue('workbench.reduceTransparency');
|
||||
this._onDidChangeReducedTransparency.fire();
|
||||
}
|
||||
}));
|
||||
updateContextKey();
|
||||
this._register(this.onDidChangeScreenReaderOptimized(() => updateContextKey()));
|
||||
@@ -53,9 +61,14 @@ export class AccessibilityService extends Disposable implements IAccessibilitySe
|
||||
this._systemMotionReduced = reduceMotionMatcher.matches;
|
||||
this._configMotionReduced = this._configurationService.getValue<'auto' | 'on' | 'off'>('workbench.reduceMotion');
|
||||
|
||||
const reduceTransparencyMatcher = mainWindow.matchMedia(`(prefers-reduced-transparency: reduce)`);
|
||||
this._systemTransparencyReduced = reduceTransparencyMatcher.matches;
|
||||
this._configTransparencyReduced = this._configurationService.getValue<'auto' | 'on' | 'off'>('workbench.reduceTransparency');
|
||||
|
||||
this._linkUnderlinesEnabled = this._configurationService.getValue('accessibility.underlineLinks');
|
||||
|
||||
this.initReducedMotionListeners(reduceMotionMatcher);
|
||||
this.initReducedTransparencyListeners(reduceTransparencyMatcher);
|
||||
this.initLinkUnderlineListeners();
|
||||
}
|
||||
|
||||
@@ -78,6 +91,24 @@ export class AccessibilityService extends Disposable implements IAccessibilitySe
|
||||
this._register(this.onDidChangeReducedMotion(() => updateRootClasses()));
|
||||
}
|
||||
|
||||
private initReducedTransparencyListeners(reduceTransparencyMatcher: MediaQueryList) {
|
||||
|
||||
this._register(addDisposableListener(reduceTransparencyMatcher, 'change', () => {
|
||||
this._systemTransparencyReduced = reduceTransparencyMatcher.matches;
|
||||
if (this._configTransparencyReduced === 'auto') {
|
||||
this._onDidChangeReducedTransparency.fire();
|
||||
}
|
||||
}));
|
||||
|
||||
const updateRootClasses = () => {
|
||||
const reduce = this.isTransparencyReduced();
|
||||
this._layoutService.mainContainer.classList.toggle('monaco-reduce-transparency', reduce);
|
||||
};
|
||||
|
||||
updateRootClasses();
|
||||
this._register(this.onDidChangeReducedTransparency(() => updateRootClasses()));
|
||||
}
|
||||
|
||||
private initLinkUnderlineListeners() {
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('accessibility.underlineLinks')) {
|
||||
@@ -119,6 +150,15 @@ export class AccessibilityService extends Disposable implements IAccessibilitySe
|
||||
return config === 'on' || (config === 'auto' && this._systemMotionReduced);
|
||||
}
|
||||
|
||||
get onDidChangeReducedTransparency(): Event<void> {
|
||||
return this._onDidChangeReducedTransparency.event;
|
||||
}
|
||||
|
||||
isTransparencyReduced(): boolean {
|
||||
const config = this._configTransparencyReduced;
|
||||
return config === 'on' || (config === 'auto' && this._systemTransparencyReduced);
|
||||
}
|
||||
|
||||
alwaysUnderlineAccessKeys(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@ export interface IAccessibilityService {
|
||||
|
||||
readonly onDidChangeScreenReaderOptimized: Event<void>;
|
||||
readonly onDidChangeReducedMotion: Event<void>;
|
||||
readonly onDidChangeReducedTransparency: Event<void>;
|
||||
|
||||
alwaysUnderlineAccessKeys(): Promise<boolean>;
|
||||
isScreenReaderOptimized(): boolean;
|
||||
isMotionReduced(): boolean;
|
||||
isTransparencyReduced(): boolean;
|
||||
getAccessibilitySupport(): AccessibilitySupport;
|
||||
setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void;
|
||||
alert(message: string): void;
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import assert from 'assert';
|
||||
import { Event } from '../../../../base/common/event.js';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
|
||||
import { TestInstantiationService } from '../../../instantiation/test/common/instantiationServiceMock.js';
|
||||
import { IConfigurationService, IConfigurationChangeEvent } from '../../../configuration/common/configuration.js';
|
||||
import { TestConfigurationService } from '../../../configuration/test/common/testConfigurationService.js';
|
||||
import { IContextKeyService } from '../../../contextkey/common/contextkey.js';
|
||||
import { MockContextKeyService } from '../../../keybinding/test/common/mockKeybindingService.js';
|
||||
import { ILayoutService } from '../../../layout/browser/layoutService.js';
|
||||
import { AccessibilityService } from '../../browser/accessibilityService.js';
|
||||
|
||||
suite('AccessibilityService', () => {
|
||||
const store = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
let configurationService: TestConfigurationService;
|
||||
let container: HTMLElement;
|
||||
|
||||
function createService(config: Record<string, unknown> = {}): AccessibilityService {
|
||||
const instantiationService = store.add(new TestInstantiationService());
|
||||
|
||||
configurationService = new TestConfigurationService({
|
||||
'editor.accessibilitySupport': 'off',
|
||||
'workbench.reduceMotion': 'off',
|
||||
'workbench.reduceTransparency': 'off',
|
||||
'accessibility.underlineLinks': false,
|
||||
...config,
|
||||
});
|
||||
instantiationService.stub(IConfigurationService, configurationService);
|
||||
|
||||
instantiationService.stub(IContextKeyService, store.add(new MockContextKeyService()));
|
||||
|
||||
container = document.createElement('div');
|
||||
instantiationService.stub(ILayoutService, {
|
||||
mainContainer: container,
|
||||
activeContainer: container,
|
||||
getContainer() { return container; },
|
||||
onDidLayoutContainer: Event.None,
|
||||
});
|
||||
|
||||
return store.add(instantiationService.createInstance(AccessibilityService));
|
||||
}
|
||||
|
||||
suite('isTransparencyReduced', () => {
|
||||
|
||||
test('returns false when config is off', () => {
|
||||
const service = createService({ 'workbench.reduceTransparency': 'off' });
|
||||
assert.strictEqual(service.isTransparencyReduced(), false);
|
||||
});
|
||||
|
||||
test('returns true when config is on', () => {
|
||||
const service = createService({ 'workbench.reduceTransparency': 'on' });
|
||||
assert.strictEqual(service.isTransparencyReduced(), true);
|
||||
});
|
||||
|
||||
test('adds CSS class when config is on', () => {
|
||||
createService({ 'workbench.reduceTransparency': 'on' });
|
||||
assert.strictEqual(container.classList.contains('monaco-reduce-transparency'), true);
|
||||
});
|
||||
|
||||
test('does not add CSS class when config is off', () => {
|
||||
createService({ 'workbench.reduceTransparency': 'off' });
|
||||
assert.strictEqual(container.classList.contains('monaco-reduce-transparency'), false);
|
||||
});
|
||||
|
||||
test('fires event and updates class on config change', () => {
|
||||
const service = createService({ 'workbench.reduceTransparency': 'off' });
|
||||
assert.strictEqual(service.isTransparencyReduced(), false);
|
||||
|
||||
let fired = false;
|
||||
store.add(service.onDidChangeReducedTransparency(() => { fired = true; }));
|
||||
|
||||
// Simulate config change
|
||||
configurationService.setUserConfiguration('workbench.reduceTransparency', 'on');
|
||||
configurationService.onDidChangeConfigurationEmitter.fire({
|
||||
affectsConfiguration(id: string) { return id === 'workbench.reduceTransparency'; },
|
||||
} satisfies Partial<IConfigurationChangeEvent> as unknown as IConfigurationChangeEvent);
|
||||
|
||||
assert.strictEqual(fired, true);
|
||||
assert.strictEqual(service.isTransparencyReduced(), true);
|
||||
assert.strictEqual(container.classList.contains('monaco-reduce-transparency'), true);
|
||||
});
|
||||
});
|
||||
|
||||
suite('isMotionReduced', () => {
|
||||
|
||||
test('returns false when config is off', () => {
|
||||
const service = createService({ 'workbench.reduceMotion': 'off' });
|
||||
assert.strictEqual(service.isMotionReduced(), false);
|
||||
});
|
||||
|
||||
test('returns true when config is on', () => {
|
||||
const service = createService({ 'workbench.reduceMotion': 'on' });
|
||||
assert.strictEqual(service.isMotionReduced(), true);
|
||||
});
|
||||
|
||||
test('adds CSS classes when config is on', () => {
|
||||
createService({ 'workbench.reduceMotion': 'on' });
|
||||
assert.strictEqual(container.classList.contains('monaco-reduce-motion'), true);
|
||||
assert.strictEqual(container.classList.contains('monaco-enable-motion'), false);
|
||||
});
|
||||
|
||||
test('adds CSS classes when config is off', () => {
|
||||
createService({ 'workbench.reduceMotion': 'off' });
|
||||
assert.strictEqual(container.classList.contains('monaco-reduce-motion'), false);
|
||||
assert.strictEqual(container.classList.contains('monaco-enable-motion'), true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -12,9 +12,11 @@ export class TestAccessibilityService implements IAccessibilityService {
|
||||
|
||||
onDidChangeScreenReaderOptimized = Event.None;
|
||||
onDidChangeReducedMotion = Event.None;
|
||||
onDidChangeReducedTransparency = Event.None;
|
||||
|
||||
isScreenReaderOptimized(): boolean { return false; }
|
||||
isMotionReduced(): boolean { return true; }
|
||||
isTransparencyReduced(): boolean { return false; }
|
||||
alwaysUnderlineAccessKeys(): Promise<boolean> { return Promise.resolve(false); }
|
||||
setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void { }
|
||||
getAccessibilitySupport(): AccessibilitySupport { return AccessibilitySupport.Unknown; }
|
||||
|
||||
@@ -715,6 +715,18 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
tags: ['accessibility'],
|
||||
enum: ['on', 'off', 'auto']
|
||||
},
|
||||
'workbench.reduceTransparency': {
|
||||
type: 'string',
|
||||
description: localize('workbench.reduceTransparency', "Controls whether the workbench should render with fewer transparency and blur effects for improved performance."),
|
||||
'enumDescriptions': [
|
||||
localize('workbench.reduceTransparency.on', "Always render without transparency and blur effects."),
|
||||
localize('workbench.reduceTransparency.off', "Do not reduce transparency and blur effects."),
|
||||
localize('workbench.reduceTransparency.auto', "Reduce transparency and blur effects based on OS configuration."),
|
||||
],
|
||||
default: 'off',
|
||||
tags: ['accessibility'],
|
||||
enum: ['on', 'off', 'auto']
|
||||
},
|
||||
'workbench.navigationControl.enabled': {
|
||||
'type': 'boolean',
|
||||
'default': true,
|
||||
|
||||
Reference in New Issue
Block a user