Path: blob/main/src/vs/platform/accessibility/browser/accessibilityService.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 { addDisposableListener } from '../../../base/browser/dom.js';6import { alert, status } from '../../../base/browser/ui/aria/aria.js';7import { mainWindow } from '../../../base/browser/window.js';8import { Emitter, Event } from '../../../base/common/event.js';9import { Disposable } from '../../../base/common/lifecycle.js';10import { AccessibilitySupport, CONTEXT_ACCESSIBILITY_MODE_ENABLED, IAccessibilityService } from '../common/accessibility.js';11import { IConfigurationService } from '../../configuration/common/configuration.js';12import { IContextKey, IContextKeyService } from '../../contextkey/common/contextkey.js';13import { ILayoutService } from '../../layout/browser/layoutService.js';1415export class AccessibilityService extends Disposable implements IAccessibilityService {16declare readonly _serviceBrand: undefined;1718private _accessibilityModeEnabledContext: IContextKey<boolean>;19protected _accessibilitySupport = AccessibilitySupport.Unknown;20protected readonly _onDidChangeScreenReaderOptimized = new Emitter<void>();2122protected _configMotionReduced: 'auto' | 'on' | 'off';23protected _systemMotionReduced: boolean;24protected readonly _onDidChangeReducedMotion = new Emitter<void>();2526private _linkUnderlinesEnabled: boolean;27protected readonly _onDidChangeLinkUnderline = new Emitter<void>();2829constructor(30@IContextKeyService private readonly _contextKeyService: IContextKeyService,31@ILayoutService private readonly _layoutService: ILayoutService,32@IConfigurationService protected readonly _configurationService: IConfigurationService33) {34super();35this._accessibilityModeEnabledContext = CONTEXT_ACCESSIBILITY_MODE_ENABLED.bindTo(this._contextKeyService);3637const updateContextKey = () => this._accessibilityModeEnabledContext.set(this.isScreenReaderOptimized());38this._register(this._configurationService.onDidChangeConfiguration(e => {39if (e.affectsConfiguration('editor.accessibilitySupport')) {40updateContextKey();41this._onDidChangeScreenReaderOptimized.fire();42}43if (e.affectsConfiguration('workbench.reduceMotion')) {44this._configMotionReduced = this._configurationService.getValue('workbench.reduceMotion');45this._onDidChangeReducedMotion.fire();46}47}));48updateContextKey();49this._register(this.onDidChangeScreenReaderOptimized(() => updateContextKey()));5051const reduceMotionMatcher = mainWindow.matchMedia(`(prefers-reduced-motion: reduce)`);52this._systemMotionReduced = reduceMotionMatcher.matches;53this._configMotionReduced = this._configurationService.getValue<'auto' | 'on' | 'off'>('workbench.reduceMotion');5455this._linkUnderlinesEnabled = this._configurationService.getValue('accessibility.underlineLinks');5657this.initReducedMotionListeners(reduceMotionMatcher);58this.initLinkUnderlineListeners();59}6061private initReducedMotionListeners(reduceMotionMatcher: MediaQueryList) {6263this._register(addDisposableListener(reduceMotionMatcher, 'change', () => {64this._systemMotionReduced = reduceMotionMatcher.matches;65if (this._configMotionReduced === 'auto') {66this._onDidChangeReducedMotion.fire();67}68}));6970const updateRootClasses = () => {71const reduce = this.isMotionReduced();72this._layoutService.mainContainer.classList.toggle('reduce-motion', reduce);73this._layoutService.mainContainer.classList.toggle('enable-motion', !reduce);74};7576updateRootClasses();77this._register(this.onDidChangeReducedMotion(() => updateRootClasses()));78}7980private initLinkUnderlineListeners() {81this._register(this._configurationService.onDidChangeConfiguration(e => {82if (e.affectsConfiguration('accessibility.underlineLinks')) {83const linkUnderlinesEnabled = this._configurationService.getValue<boolean>('accessibility.underlineLinks');84this._linkUnderlinesEnabled = linkUnderlinesEnabled;85this._onDidChangeLinkUnderline.fire();86}87}));8889const updateLinkUnderlineClasses = () => {90const underlineLinks = this._linkUnderlinesEnabled;91this._layoutService.mainContainer.classList.toggle('underline-links', underlineLinks);92};9394updateLinkUnderlineClasses();9596this._register(this.onDidChangeLinkUnderlines(() => updateLinkUnderlineClasses()));97}9899public onDidChangeLinkUnderlines(listener: () => void) {100return this._onDidChangeLinkUnderline.event(listener);101}102103get onDidChangeScreenReaderOptimized(): Event<void> {104return this._onDidChangeScreenReaderOptimized.event;105}106107isScreenReaderOptimized(): boolean {108const config = this._configurationService.getValue('editor.accessibilitySupport');109return config === 'on' || (config === 'auto' && this._accessibilitySupport === AccessibilitySupport.Enabled);110}111112get onDidChangeReducedMotion(): Event<void> {113return this._onDidChangeReducedMotion.event;114}115116isMotionReduced(): boolean {117const config = this._configMotionReduced;118return config === 'on' || (config === 'auto' && this._systemMotionReduced);119}120121alwaysUnderlineAccessKeys(): Promise<boolean> {122return Promise.resolve(false);123}124125getAccessibilitySupport(): AccessibilitySupport {126return this._accessibilitySupport;127}128129setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void {130if (this._accessibilitySupport === accessibilitySupport) {131return;132}133134this._accessibilitySupport = accessibilitySupport;135this._onDidChangeScreenReaderOptimized.fire();136}137138alert(message: string): void {139alert(message);140}141142status(message: string): void {143status(message);144}145}146147148