diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts index 33631c0bade96..c08a26dccc9cf 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibility.contribution.ts @@ -10,11 +10,12 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle import { Registry } from 'vs/platform/registry/common/platform'; import { IAccessibleViewService, AccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { UnfocusedViewDimmingContribution } from 'vs/workbench/contrib/accessibility/browser/unfocusedViewDimmingContribution'; -import { EditorAccessibilityHelpContribution, HoverAccessibleViewContribution, InlineCompletionsAccessibleViewContribution, NotificationAccessibleViewContribution } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions'; +import { HoverAccessibleViewContribution, InlineCompletionsAccessibleViewContribution, NotificationAccessibleViewContribution } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions'; import { AccessibilityStatus } from 'vs/workbench/contrib/accessibility/browser/accessibilityStatus'; import { CommentsAccessibilityHelpContribution } from 'vs/workbench/contrib/comments/browser/comments.contribution'; import { IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility'; import { AccessibleNotificationService } from 'vs/workbench/contrib/accessibility/browser/accessibleNotificationService'; +import { EditorAccessibilityHelpContribution } from 'vs/workbench/contrib/accessibility/browser/editorAccessibilityHelp'; registerAccessibilityConfiguration(); registerSingleton(IAccessibleViewService, AccessibleViewService, InstantiationType.Delayed); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts index 0f337d2221868..e3d2a99f7b7d5 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts @@ -24,7 +24,8 @@ export const accessibleViewCurrentProviderId = new RawContextKey('access export const enum AccessibilityWorkbenchSettingId { DimUnfocusedEnabled = 'accessibility.dimUnfocused.enabled', DimUnfocusedOpacity = 'accessibility.dimUnfocused.opacity', - HideAccessibleView = 'accessibility.hideAccessibleView' + HideAccessibleView = 'accessibility.hideAccessibleView', + AccessibleViewCloseOnKeyPress = 'accessibility.accessibleView.closeOnKeyPress' } export const enum ViewDimUnfocusedOpacityProperties { @@ -159,7 +160,12 @@ const configuration: IConfigurationNode = { 'default': SpeechTimeoutDefault, 'minimum': 0, 'tags': ['accessibility'] - } + }, + [AccessibilityWorkbenchSettingId.AccessibleViewCloseOnKeyPress]: { + markdownDescription: localize('terminal.integrated.accessibleView.closeOnKeyPress', "On keypress, close the accessible view and focus the element from which it was invoked."), + type: 'boolean', + default: true + }, } }; diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts index 3ba18948dc87b..3daba2ea93e9a 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibilityContributions.ts @@ -9,25 +9,19 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable } from 'vs/base/common/lifecycle'; -import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; -import { EditorOption } from 'vs/editor/common/config/editorOptions'; -import { AccessibilityHelpNLS } from 'vs/editor/common/standaloneStrings'; -import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/browser/toggleTabFocusMode'; import { localize } from 'vs/nls'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { AccessibilityVerbositySettingId, AccessibleViewProviderId, accessibleViewIsShown } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration'; import * as strings from 'vs/base/common/strings'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileConstants'; import { ModesHoverController } from 'vs/editor/contrib/hover/browser/hover'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { getNotificationFromContext } from 'vs/workbench/browser/parts/notifications/notificationsCommands'; import { IListService, WorkbenchList } from 'vs/platform/list/browser/listService'; import { NotificationFocusedContext } from 'vs/workbench/common/contextkeys'; -import { IAccessibleViewService, IAccessibleContentProvider, IAccessibleViewOptions, AccessibleViewType } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; +import { IAccessibleViewService, IAccessibleViewOptions, AccessibleViewType } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { IHoverService } from 'vs/workbench/services/hover/browser/hover'; import { alert } from 'vs/base/browser/ui/aria/aria'; import { AccessibilityHelpAction, AccessibleViewAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions'; @@ -37,124 +31,10 @@ import { ThemeIcon } from 'vs/base/common/themables'; import { Codicon } from 'vs/base/common/codicons'; import { InlineCompletionsController } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionsController'; import { InlineCompletionContextKeys } from 'vs/editor/contrib/inlineCompletions/browser/inlineCompletionContextKeys'; -import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys'; -import { CommentAccessibilityHelpNLS } from 'vs/workbench/contrib/comments/browser/comments.contribution'; -import { CommentCommandId } from 'vs/workbench/contrib/comments/common/commentCommandIds'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { AudioCue } from 'vs/platform/audioCues/browser/audioCueService'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; import { AccessibleNotificationEvent, IAccessibleNotificationService } from 'vs/platform/accessibility/common/accessibility'; -export class EditorAccessibilityHelpContribution extends Disposable { - static ID: 'editorAccessibilityHelpContribution'; - constructor() { - super(); - this._register(AccessibilityHelpAction.addImplementation(95, 'editor', async accessor => { - const codeEditorService = accessor.get(ICodeEditorService); - const accessibleViewService = accessor.get(IAccessibleViewService); - const instantiationService = accessor.get(IInstantiationService); - const commandService = accessor.get(ICommandService); - let codeEditor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor(); - if (!codeEditor) { - await commandService.executeCommand(NEW_UNTITLED_FILE_COMMAND_ID); - codeEditor = codeEditorService.getActiveCodeEditor()!; - } - accessibleViewService.show(instantiationService.createInstance(EditorAccessibilityHelpProvider, codeEditor)); - }, EditorContextKeys.focus)); - } -} - -class EditorAccessibilityHelpProvider implements IAccessibleContentProvider { - id = AccessibleViewProviderId.Editor; - onClose() { - this._editor.focus(); - } - options: IAccessibleViewOptions = { type: AccessibleViewType.Help, readMoreUrl: 'https://go.microsoft.com/fwlink/?linkid=851010' }; - verbositySettingKey = AccessibilityVerbositySettingId.Editor; - constructor( - private readonly _editor: ICodeEditor, - @IKeybindingService private readonly _keybindingService: IKeybindingService, - @IContextKeyService private readonly _contextKeyService: IContextKeyService, - @IConfigurationService private readonly _configurationService: IConfigurationService - ) { - } - - provideContent(): string { - const options = this._editor.getOptions(); - const content = []; - - if (options.get(EditorOption.inDiffEditor)) { - if (options.get(EditorOption.readOnly)) { - content.push(AccessibilityHelpNLS.readonlyDiffEditor); - } else { - content.push(AccessibilityHelpNLS.editableDiffEditor); - } - } else { - if (options.get(EditorOption.readOnly)) { - content.push(AccessibilityHelpNLS.readonlyEditor); - } else { - content.push(AccessibilityHelpNLS.editableEditor); - } - } - const saveAudioCue = this._configurationService.getValue(AudioCue.save.settingsKey); - switch (saveAudioCue) { - case 'never': - content.push(AccessibilityHelpNLS.saveAudioCueDisabled); - break; - case 'always': - content.push(AccessibilityHelpNLS.saveAudioCueAlways); - break; - case 'userGesture': - content.push(AccessibilityHelpNLS.saveAudioCueUserGesture); - break; - } - const formatAudioCue = this._configurationService.getValue(AudioCue.format.settingsKey); - switch (formatAudioCue) { - case 'never': - content.push(AccessibilityHelpNLS.formatAudioCueDisabled); - break; - case 'always': - content.push(AccessibilityHelpNLS.formatAudioCueAlways); - break; - case 'userGesture': - content.push(AccessibilityHelpNLS.formatAudioCueUserGesture); - break; - } - - const commentCommandInfo = getCommentCommandInfo(this._keybindingService, this._contextKeyService, this._editor); - if (commentCommandInfo) { - content.push(commentCommandInfo); - } - - if (options.get(EditorOption.stickyScroll).enabled) { - content.push(descriptionForCommand('editor.action.focusStickyScroll', AccessibilityHelpNLS.stickScrollKb, AccessibilityHelpNLS.stickScrollNoKb, this._keybindingService)); - } - - if (options.get(EditorOption.tabFocusMode)) { - content.push(descriptionForCommand(ToggleTabFocusModeAction.ID, AccessibilityHelpNLS.tabFocusModeOnMsg, AccessibilityHelpNLS.tabFocusModeOnMsgNoKb, this._keybindingService)); - } else { - content.push(descriptionForCommand(ToggleTabFocusModeAction.ID, AccessibilityHelpNLS.tabFocusModeOffMsg, AccessibilityHelpNLS.tabFocusModeOffMsgNoKb, this._keybindingService)); - } - return content.join('\n\n'); - } -} - -export function getCommentCommandInfo(keybindingService: IKeybindingService, contextKeyService: IContextKeyService, editor: ICodeEditor): string | undefined { - const editorContext = contextKeyService.getContext(editor.getDomNode()!); - if (editorContext.getValue(CommentContextKeys.activeEditorHasCommentingRange.key)) { - const commentCommandInfo: string[] = []; - commentCommandInfo.push(CommentAccessibilityHelpNLS.intro); - commentCommandInfo.push(descriptionForCommand(CommentCommandId.Add, CommentAccessibilityHelpNLS.addComment, CommentAccessibilityHelpNLS.addCommentNoKb, keybindingService)); - commentCommandInfo.push(descriptionForCommand(CommentCommandId.NextThread, CommentAccessibilityHelpNLS.nextCommentThreadKb, CommentAccessibilityHelpNLS.nextCommentThreadNoKb, keybindingService)); - commentCommandInfo.push(descriptionForCommand(CommentCommandId.PreviousThread, CommentAccessibilityHelpNLS.previousCommentThreadKb, CommentAccessibilityHelpNLS.previousCommentThreadNoKb, keybindingService)); - commentCommandInfo.push(descriptionForCommand(CommentCommandId.NextRange, CommentAccessibilityHelpNLS.nextRange, CommentAccessibilityHelpNLS.nextRangeNoKb, keybindingService)); - commentCommandInfo.push(descriptionForCommand(CommentCommandId.PreviousRange, CommentAccessibilityHelpNLS.previousRange, CommentAccessibilityHelpNLS.previousRangeNoKb, keybindingService)); - return commentCommandInfo.join('\n'); - } - return; -} - -function descriptionForCommand(commandId: string, msg: string, noKbMsg: string, keybindingService: IKeybindingService): string { +export function descriptionForCommand(commandId: string, msg: string, noKbMsg: string, keybindingService: IKeybindingService): string { const kb = keybindingService.lookupKeybinding(commandId); if (kb) { return strings.format(msg, kb.getAriaLabel()); diff --git a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts index f2300e1afaffd..f09169d8b27fe 100644 --- a/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts +++ b/src/vs/workbench/contrib/accessibility/browser/accessibleView.ts @@ -508,7 +508,7 @@ export class AccessibleView extends Disposable { }; const disposableStore = new DisposableStore(); disposableStore.add(this._editorWidget.onKeyDown((e) => { - if (e.keyCode === KeyCode.Escape || shouldHide(e.browserEvent, this._keybindingService)) { + if (e.keyCode === KeyCode.Escape || shouldHide(e.browserEvent, this._keybindingService, this._configurationService)) { hide(e); } else if (e.keyCode === KeyCode.KeyH && provider.options.readMoreUrl) { const url: string = provider.options.readMoreUrl!; @@ -766,7 +766,10 @@ export interface IAccessibleViewSymbol extends IPickerQuickAccessItem { lineNumber?: number; } -function shouldHide(event: KeyboardEvent, keybindingService: IKeybindingService): boolean { +function shouldHide(event: KeyboardEvent, keybindingService: IKeybindingService, configurationService: IConfigurationService): boolean { + if (!configurationService.getValue(AccessibilityWorkbenchSettingId.AccessibleViewCloseOnKeyPress)) { + return false; + } const standardKeyboardEvent = new StandardKeyboardEvent(event); const resolveResult = keybindingService.softDispatch(standardKeyboardEvent, standardKeyboardEvent.target); diff --git a/src/vs/workbench/contrib/accessibility/browser/editorAccessibilityHelp.ts b/src/vs/workbench/contrib/accessibility/browser/editorAccessibilityHelp.ts new file mode 100644 index 0000000000000..1bd79ceb9a39a --- /dev/null +++ b/src/vs/workbench/contrib/accessibility/browser/editorAccessibilityHelp.ts @@ -0,0 +1,135 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable } from 'vs/base/common/lifecycle'; +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService'; +import { EditorOption } from 'vs/editor/common/config/editorOptions'; +import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; +import { AccessibilityHelpNLS } from 'vs/editor/common/standaloneStrings'; +import { ToggleTabFocusModeAction } from 'vs/editor/contrib/toggleTabFocusMode/browser/toggleTabFocusMode'; +import { AudioCue } from 'vs/platform/audioCues/browser/audioCueService'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { AccessibleViewProviderId, AccessibilityVerbositySettingId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration'; +import { descriptionForCommand } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions'; +import { IAccessibleViewService, IAccessibleContentProvider, IAccessibleViewOptions, AccessibleViewType } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; +import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions'; +import { CommentAccessibilityHelpNLS } from 'vs/workbench/contrib/comments/browser/comments.contribution'; +import { CommentCommandId } from 'vs/workbench/contrib/comments/common/commentCommandIds'; +import { CommentContextKeys } from 'vs/workbench/contrib/comments/common/commentContextKeys'; +import { NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileConstants'; + +export class EditorAccessibilityHelpContribution extends Disposable { + static ID: 'editorAccessibilityHelpContribution'; + constructor() { + super(); + this._register(AccessibilityHelpAction.addImplementation(95, 'editor', async accessor => { + const codeEditorService = accessor.get(ICodeEditorService); + const accessibleViewService = accessor.get(IAccessibleViewService); + const instantiationService = accessor.get(IInstantiationService); + const commandService = accessor.get(ICommandService); + let codeEditor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor(); + if (!codeEditor) { + await commandService.executeCommand(NEW_UNTITLED_FILE_COMMAND_ID); + codeEditor = codeEditorService.getActiveCodeEditor()!; + } + accessibleViewService.show(instantiationService.createInstance(EditorAccessibilityHelpProvider, codeEditor)); + }, EditorContextKeys.focus)); + } +} + +class EditorAccessibilityHelpProvider implements IAccessibleContentProvider { + id = AccessibleViewProviderId.Editor; + onClose() { + this._editor.focus(); + } + options: IAccessibleViewOptions = { type: AccessibleViewType.Help, readMoreUrl: 'https://go.microsoft.com/fwlink/?linkid=851010' }; + verbositySettingKey = AccessibilityVerbositySettingId.Editor; + constructor( + private readonly _editor: ICodeEditor, + @IKeybindingService private readonly _keybindingService: IKeybindingService, + @IContextKeyService private readonly _contextKeyService: IContextKeyService, + @IConfigurationService private readonly _configurationService: IConfigurationService + ) { + } + + provideContent(): string { + const options = this._editor.getOptions(); + const content = []; + + if (options.get(EditorOption.inDiffEditor)) { + if (options.get(EditorOption.readOnly)) { + content.push(AccessibilityHelpNLS.readonlyDiffEditor); + } else { + content.push(AccessibilityHelpNLS.editableDiffEditor); + } + } else { + if (options.get(EditorOption.readOnly)) { + content.push(AccessibilityHelpNLS.readonlyEditor); + } else { + content.push(AccessibilityHelpNLS.editableEditor); + } + } + const saveAudioCue = this._configurationService.getValue(AudioCue.save.settingsKey); + switch (saveAudioCue) { + case 'never': + content.push(AccessibilityHelpNLS.saveAudioCueDisabled); + break; + case 'always': + content.push(AccessibilityHelpNLS.saveAudioCueAlways); + break; + case 'userGesture': + content.push(AccessibilityHelpNLS.saveAudioCueUserGesture); + break; + } + const formatAudioCue = this._configurationService.getValue(AudioCue.format.settingsKey); + switch (formatAudioCue) { + case 'never': + content.push(AccessibilityHelpNLS.formatAudioCueDisabled); + break; + case 'always': + content.push(AccessibilityHelpNLS.formatAudioCueAlways); + break; + case 'userGesture': + content.push(AccessibilityHelpNLS.formatAudioCueUserGesture); + break; + } + + const commentCommandInfo = getCommentCommandInfo(this._keybindingService, this._contextKeyService, this._editor); + if (commentCommandInfo) { + content.push(commentCommandInfo); + } + + if (options.get(EditorOption.stickyScroll).enabled) { + content.push(descriptionForCommand('editor.action.focusStickyScroll', AccessibilityHelpNLS.stickScrollKb, AccessibilityHelpNLS.stickScrollNoKb, this._keybindingService)); + } + + if (options.get(EditorOption.tabFocusMode)) { + content.push(descriptionForCommand(ToggleTabFocusModeAction.ID, AccessibilityHelpNLS.tabFocusModeOnMsg, AccessibilityHelpNLS.tabFocusModeOnMsgNoKb, this._keybindingService)); + } else { + content.push(descriptionForCommand(ToggleTabFocusModeAction.ID, AccessibilityHelpNLS.tabFocusModeOffMsg, AccessibilityHelpNLS.tabFocusModeOffMsgNoKb, this._keybindingService)); + } + return content.join('\n\n'); + } +} + +export function getCommentCommandInfo(keybindingService: IKeybindingService, contextKeyService: IContextKeyService, editor: ICodeEditor): string | undefined { + const editorContext = contextKeyService.getContext(editor.getDomNode()!); + if (editorContext.getValue(CommentContextKeys.activeEditorHasCommentingRange.key)) { + const commentCommandInfo: string[] = []; + commentCommandInfo.push(CommentAccessibilityHelpNLS.intro); + commentCommandInfo.push(descriptionForCommand(CommentCommandId.Add, CommentAccessibilityHelpNLS.addComment, CommentAccessibilityHelpNLS.addCommentNoKb, keybindingService)); + commentCommandInfo.push(descriptionForCommand(CommentCommandId.NextThread, CommentAccessibilityHelpNLS.nextCommentThreadKb, CommentAccessibilityHelpNLS.nextCommentThreadNoKb, keybindingService)); + commentCommandInfo.push(descriptionForCommand(CommentCommandId.PreviousThread, CommentAccessibilityHelpNLS.previousCommentThreadKb, CommentAccessibilityHelpNLS.previousCommentThreadNoKb, keybindingService)); + commentCommandInfo.push(descriptionForCommand(CommentCommandId.NextRange, CommentAccessibilityHelpNLS.nextRange, CommentAccessibilityHelpNLS.nextRangeNoKb, keybindingService)); + commentCommandInfo.push(descriptionForCommand(CommentCommandId.PreviousRange, CommentAccessibilityHelpNLS.previousRange, CommentAccessibilityHelpNLS.previousRangeNoKb, keybindingService)); + return commentCommandInfo.join('\n'); + } + return; +} diff --git a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts index 666ea74dd6a83..cfbcd71273a60 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/diffEditorHelper.ts @@ -22,9 +22,9 @@ import { Registry } from 'vs/platform/registry/common/platform'; import { FloatingEditorClickWidget } from 'vs/workbench/browser/codeeditor'; import { Extensions, IConfigurationMigrationRegistry } from 'vs/workbench/common/configuration'; import { AccessibilityVerbositySettingId, AccessibleViewProviderId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration'; -import { getCommentCommandInfo } from 'vs/workbench/contrib/accessibility/browser/accessibilityContributions'; import { AccessibleViewType, IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView'; import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions'; +import { getCommentCommandInfo } from 'vs/workbench/contrib/accessibility/browser/editorAccessibilityHelp'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; class DiffEditorHelperContribution extends Disposable implements IDiffEditorContribution {