diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json index b5ce6c6eabc..e49ba1d7778 100644 --- a/build/lib/i18n.resources.json +++ b/build/lib/i18n.resources.json @@ -513,6 +513,10 @@ { "name": "vs/workbench/services/localization", "project": "vscode-workbench" + }, + { + "name": "vs/workbench/contrib/accessibility", + "project": "vscode-workbench" } ] } diff --git a/src/vs/editor/browser/widget/diffEditorWidget.ts b/src/vs/editor/browser/widget/diffEditorWidget.ts index b9976679517..d538b06f6c3 100644 --- a/src/vs/editor/browser/widget/diffEditorWidget.ts +++ b/src/vs/editor/browser/widget/diffEditorWidget.ts @@ -286,6 +286,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE renderOverviewRuler: true, diffWordWrap: 'inherit', diffAlgorithm: 'advanced', + accessibilityVerbose: true }); if (typeof options.isInEmbeddedEditor !== 'undefined') { @@ -1274,7 +1275,7 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE if (options.originalAriaLabel) { result.ariaLabel = options.originalAriaLabel; } - result.ariaLabel += ariaNavigationTip; + this._updateAriaLabel(result); result.readOnly = !this._options.originalEditable; result.dropIntoEditor = { enabled: !result.readOnly }; result.extraEditorClassName = 'original-in-monaco-diff-editor'; @@ -1287,12 +1288,22 @@ export class DiffEditorWidget extends Disposable implements editorBrowser.IDiffE }; } + private _updateAriaLabel(options: IEditorConstructionOptions): void { + let ariaLabel = options.ariaLabel; + if (this._options.accessibilityVerbose) { + ariaLabel += ariaNavigationTip; + } else if (ariaLabel) { + ariaLabel = ariaLabel.replaceAll(ariaNavigationTip, ''); + } + options.ariaLabel = ariaLabel; + } + private _adjustOptionsForRightHandSide(options: Readonly): IEditorConstructionOptions { const result = this._adjustOptionsForSubEditor(options); if (options.modifiedAriaLabel) { result.ariaLabel = options.modifiedAriaLabel; } - result.ariaLabel += ariaNavigationTip; + this._updateAriaLabel(result); result.wordWrapOverride1 = this._options.diffWordWrap; result.revealHorizontalRightPadding = EditorOptions.revealHorizontalRightPadding.defaultValue + DiffEditorWidget.ENTIRE_DIFF_OVERVIEW_WIDTH; result.scrollbar!.verticalHasArrows = false; @@ -2767,6 +2778,7 @@ function validateDiffEditorOptions(options: Readonly, defaul renderOverviewRuler: validateBooleanOption(options.renderOverviewRuler, defaults.renderOverviewRuler), diffWordWrap: validateDiffWordWrap(options.diffWordWrap, defaults.diffWordWrap), diffAlgorithm: validateStringSetOption(options.diffAlgorithm, defaults.diffAlgorithm, ['legacy', 'advanced'], { 'smart': 'legacy', 'experimental': 'advanced' }), + accessibilityVerbose: validateBooleanOption(options.accessibilityVerbose, defaults.accessibilityVerbose), }; } diff --git a/src/vs/editor/browser/widget/diffReview.ts b/src/vs/editor/browser/widget/diffReview.ts index f768f14750e..1d9316b02a6 100644 --- a/src/vs/editor/browser/widget/diffReview.ts +++ b/src/vs/editor/browser/widget/diffReview.ts @@ -30,10 +30,11 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { Constants } from 'vs/base/common/uint'; import { Codicon } from 'vs/base/common/codicons'; import { registerIcon } from 'vs/platform/theme/common/iconRegistry'; -import { ILanguageIdCodec } from 'vs/editor/common/languages'; import { ILanguageService } from 'vs/editor/common/languages/language'; -import { ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { ILineChange } from 'vs/editor/common/diff/smartLinesDiffComputer'; +import { ILanguageIdCodec } from 'vs/editor/common/languages'; const DIFF_LINES_PADDING = 3; @@ -102,7 +103,8 @@ export class DiffReview extends Disposable { constructor( diffEditor: DiffEditorWidget, @ILanguageService private readonly _languageService: ILanguageService, - @IAudioCueService private readonly _audioCueService: IAudioCueService + @IAudioCueService private readonly _audioCueService: IAudioCueService, + @IConfigurationService private readonly _configurationService: IConfigurationService ) { super(); this._diffEditor = diffEditor; @@ -180,6 +182,11 @@ export class DiffReview extends Disposable { this.accept(); } })); + this._register(this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('accessibility.verbosity.diff-editor')) { + this._diffEditor.updateOptions({ accessibilityVerbose: this._configurationService.getValue('accessibility.verbosity.diff-editor') }); + } + })); this._diffs = []; this._currentDiff = null; } diff --git a/src/vs/editor/common/config/editorOptions.ts b/src/vs/editor/common/config/editorOptions.ts index 7ed880cdcda..110b99bbaab 100644 --- a/src/vs/editor/common/config/editorOptions.ts +++ b/src/vs/editor/common/config/editorOptions.ts @@ -784,6 +784,11 @@ export interface IDiffEditorBaseOptions { * Diff Algorithm */ diffAlgorithm?: 'legacy' | 'advanced' | IDocumentDiffProvider; + + /** + * Whether the diff editor aria label should be verbose. + */ + accessibilityVerbose?: boolean; } /** diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 15091d47c20..fb1b3f52a9e 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -3836,6 +3836,10 @@ declare namespace monaco.editor { * Diff Algorithm */ diffAlgorithm?: 'legacy' | 'advanced' | IDocumentDiffProvider; + /** + * Whether the diff editor aria label should be verbose. + */ + accessibilityVerbose?: boolean; } /** diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts new file mode 100644 index 00000000000..0338c18d518 --- /dev/null +++ b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { registerAccessibilityConfiguration } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution'; + +registerAccessibilityConfiguration(); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityContribution.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityContribution.ts new file mode 100644 index 00000000000..6f63998ec5c --- /dev/null +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityContribution.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { localize } from 'vs/nls'; +import { Extensions, IConfigurationNode, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; +import { Registry } from 'vs/platform/registry/common/platform'; + +const configuration: IConfigurationNode = { + id: 'accessibility', + title: localize('accessibilityConfigurationTitle', "Accessibility"), + type: 'object', + properties: { + 'accessibility.verbosity.terminal': { + description: localize('verbosity.terminal.description', 'Provide information about how to access the terminal accessibility help menu when the terminal is focused'), + type: 'boolean', + default: true, + tags: ['accessibility'] + }, + 'accessibility.verbosity.diff-editor': { + description: localize('verbosity.diff-editor.description', 'Provide information about how to navigate changes in the diff editor when it is focused'), + type: 'boolean', + default: true, + tags: ['accessibility'] + } + } +}; + +export function registerAccessibilityConfiguration() { + const configurationRegistry = Registry.as(Extensions.Configuration); + configurationRegistry.registerConfiguration(configuration); +} diff --git a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts index 3faa5958eea..5af24beb799 100644 --- a/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts +++ b/src/vs/workbench/contrib/notebook/browser/diff/diffComponents.ts @@ -502,7 +502,8 @@ abstract class AbstractElementRenderer extends Disposable { dimension: { height: this.cell.layoutInfo.metadataHeight, width: this.cell.getComputedCellContainerWidth(this.notebookEditor.getLayoutInfo(), true, true) - } + }, + accessibilityVerbose: this.configurationService.getValue('accessibility.verbosity.diff-editor') ?? false }, { originalEditor: getOptimizedNestedCodeEditorWidgetOptions(), modifiedEditor: getOptimizedNestedCodeEditorWidgetOptions() diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index 06b11d86c13..e948dc57679 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -524,6 +524,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { }); this._register(this._configurationService.onDidChangeConfiguration(async e => { + if (e.affectsConfiguration('accessibility.verbosity.terminal')) { + this._setAriaLabel(this.xterm?.raw, this._instanceId, this.title); + } if (e.affectsConfiguration('terminal.integrated')) { this.updateConfig(); this.setVisible(this._isVisible); @@ -1942,7 +1945,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { labelParts.push(nls.localize('terminalScreenReaderMode', "Run the command: Toggle Screen Reader Accessibility Mode for an optimized screen reader experience")); } const accessibilityHelpKeybinding = this._keybindingService.lookupKeybinding(TerminalCommandId.ShowTerminalAccessibilityHelp)?.getLabel(); - if (accessibilityHelpKeybinding) { + if (this._configurationService.getValue('accessibility.verbosity.terminal') && accessibilityHelpKeybinding) { labelParts.push(nls.localize('terminalHelpAriaLabel', "Use {0} for terminal accessibility help", accessibilityHelpKeybinding)); } xterm.textarea.setAttribute('aria-label', labelParts.join('\n')); diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index c010c73133d..2aa3bf24396 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -362,4 +362,7 @@ import 'vs/workbench/contrib/deprecatedExtensionMigrator/browser/deprecatedExten // Bracket Pair Colorizer 2 Telemetry import 'vs/workbench/contrib/bracketPairColorizer2Telemetry/browser/bracketPairColorizer2Telemetry.contribution'; +// Accessibility +import 'vs/workbench/contrib/accessibility/browser/accessibility.contribution'; + //#endregion