Merge pull request #191108 from microsoft/merogge/alt-keybindings

suppport `alt+f2`, `ctrl/cmd+Up/DownArrow` to go to terminal accessible buffer, synchronize windows/mac keybinding for command nav in accessible buffer
This commit is contained in:
Megan Rogge
2023-08-24 14:16:01 -07:00
committed by GitHub
6 changed files with 55 additions and 14 deletions
@@ -495,6 +495,7 @@ export const enum TerminalCommandId {
HideSuggestWidget = 'workbench.action.terminal.hideSuggestWidget',
FocusHover = 'workbench.action.terminal.focusHover',
ShowEnvironmentContributions = 'workbench.action.terminal.showEnvironmentContributions',
FocusAndHideAccessibleBuffer = 'workbench.action.terminal.focusAndHideAccessibleBuffer',
// Developer commands
@@ -569,6 +570,7 @@ export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [
TerminalCommandId.HideSuggestWidget,
TerminalCommandId.FocusHover,
AccessibilityCommandId.OpenAccessibilityHelp,
TerminalCommandId.FocusAndHideAccessibleBuffer,
'editor.action.toggleTabFocusMode',
'notifications.hideList',
'notifications.hideToasts',
@@ -16,6 +16,7 @@ export const enum TerminalContextKeyStrings {
Focus = 'terminalFocus',
FocusInAny = 'terminalFocusInAny',
AccessibleBufferFocus = 'terminalAccessibleBufferFocus',
AccessibleBufferOnLastLine = 'terminalAccessibleBufferOnLastLine',
EditorFocus = 'terminalEditorFocus',
TabsFocus = 'terminalTabsFocus',
WebExtensionContributedProfile = 'terminalWebExtensionContributedProfile',
@@ -51,6 +52,9 @@ export namespace TerminalContextKeys {
/** Whether the accessible buffer is focused. */
export const accessibleBufferFocus = new RawContextKey<boolean>(TerminalContextKeyStrings.AccessibleBufferFocus, false, localize('terminalAccessibleBufferFocusContextKey', "Whether the terminal accessible buffer is focused."));
/** Whether the accessible buffer focus is on the last line. */
export const accessibleBufferOnLastLine = new RawContextKey<boolean>(TerminalContextKeyStrings.AccessibleBufferOnLastLine, false, localize('terminalAccessibleBufferOnLastLineContextKey', "Whether the accessible buffer focus is on the last line."));
/** Whether a terminal in the editor area is focused. */
export const editorFocus = new RawContextKey<boolean>(TerminalContextKeyStrings.EditorFocus, false, localize('terminalEditorFocusContextKey', "Whether a terminal in the editor area is focused."));
@@ -22,6 +22,10 @@ export const terminalStrings = {
value: localize('workbench.action.terminal.focus', "Focus Terminal"),
original: 'Focus Terminal'
},
focusAndHideAccessibleBuffer: {
value: localize('workbench.action.terminal.focusAndHideAccessibleBuffer', "Focus Terminal and Hide Accessible Buffer"),
original: 'Focus Terminal and Hide Accessible Buffer'
},
kill: {
value: localize('killTerminal', "Kill Terminal"),
original: 'Kill Terminal',
@@ -11,7 +11,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickPick, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { terminalTabFocusModeContextKey } from 'vs/platform/terminal/common/terminal';
import { TerminalLocation, terminalTabFocusModeContextKey } from 'vs/platform/terminal/common/terminal';
import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/browser/accessibleView';
import { AccessibilityHelpAction } from 'vs/workbench/contrib/accessibility/browser/accessibleViewActions';
import { ITerminalContribution, ITerminalInstance, ITerminalService, IXtermTerminal } from 'vs/workbench/contrib/terminal/browser/terminal';
@@ -20,6 +20,7 @@ import { registerTerminalContribution } from 'vs/workbench/contrib/terminal/brow
import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager';
import { ITerminalProcessManager, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal';
import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey';
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
import { TerminalAccessibleContentProvider } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibilityHelp';
import { AccessibleBufferWidget, NavigationType } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/terminalAccessibleBuffer';
import { TextAreaSyncAddon } from 'vs/workbench/contrib/terminalContrib/accessibility/browser/textAreaSyncAddon';
@@ -83,6 +84,9 @@ class AccessibleBufferContribution extends DisposableStore implements ITerminalC
navigateToCommand(type: NavigationType): void {
return this._accessibleBufferWidget?.navigateToCommand(type);
}
hide(): void {
this._accessibleBufferWidget?.hide();
}
}
registerTerminalContribution(AccessibleBufferContribution.ID, AccessibleBufferContribution);
@@ -114,6 +118,7 @@ registerTerminalAction({
keybinding: [
{
primary: KeyMod.Shift | KeyCode.Tab,
secondary: [KeyMod.CtrlCmd | KeyCode.UpArrow, KeyMod.Alt | KeyCode.F2],
weight: KeybindingWeight.WorkbenchContrib,
when: ContextKeyExpr.and(CONTEXT_ACCESSIBILITY_MODE_ENABLED, TerminalContextKeys.focus, ContextKeyExpr.or(terminalTabFocusModeContextKey, TerminalContextKeys.accessibleBufferFocus.negate()))
}
@@ -161,8 +166,7 @@ registerTerminalAction({
weight: KeybindingWeight.WorkbenchContrib + 2
},
{
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
mac: { primary: KeyMod.Alt | KeyCode.DownArrow },
primary: KeyMod.Alt | KeyCode.DownArrow,
when: ContextKeyExpr.and(TerminalContextKeys.accessibleBufferFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED),
weight: KeybindingWeight.WorkbenchContrib + 2
}
@@ -189,8 +193,7 @@ registerTerminalAction({
weight: KeybindingWeight.WorkbenchContrib + 2
},
{
primary: KeyMod.CtrlCmd | KeyCode.UpArrow,
mac: { primary: KeyMod.Alt | KeyCode.UpArrow },
primary: KeyMod.Alt | KeyCode.UpArrow,
when: ContextKeyExpr.and(TerminalContextKeys.accessibleBufferFocus, CONTEXT_ACCESSIBILITY_MODE_ENABLED),
weight: KeybindingWeight.WorkbenchContrib + 2
}
@@ -204,3 +207,20 @@ registerTerminalAction({
await AccessibleBufferContribution.get(instance)?.navigateToCommand(NavigationType.Previous);
}
});
registerTerminalAction({
id: TerminalCommandId.FocusAndHideAccessibleBuffer,
title: terminalStrings.focusAndHideAccessibleBuffer,
f1: false,
keybinding: {
when: ContextKeyExpr.and(TerminalContextKeys.accessibleBufferFocus, TerminalContextKeys.accessibleBufferOnLastLine),
primary: KeyMod.CtrlCmd | KeyCode.DownArrow,
weight: KeybindingWeight.WorkbenchContrib
},
precondition: ContextKeyExpr.or(TerminalContextKeys.processSupported, TerminalContextKeys.terminalHasBeenCreated),
run: async (c) => {
const instance = c.service.activeInstance || await c.service.createTerminal({ location: TerminalLocation.Panel });
instance.getContribution<AccessibleBufferContribution>(AccessibleBufferContribution.ID)?.hide();
instance.focus(true);
}
});
@@ -57,7 +57,7 @@ export class AccessibleBufferWidget extends TerminalAccessibleWidget {
@ITerminalLogService private readonly _logService: ITerminalLogService,
@ITerminalService _terminalService: ITerminalService
) {
super(ClassName.AccessibleBuffer, _instance, _xterm, TerminalContextKeys.accessibleBufferFocus, _instantiationService, _modelService, _configurationService, _contextKeyService, _terminalService);
super(ClassName.AccessibleBuffer, _instance, _xterm, TerminalContextKeys.accessibleBufferFocus, TerminalContextKeys.accessibleBufferOnLastLine, _instantiationService, _modelService, _configurationService, _contextKeyService, _terminalService);
this._bufferTracker = _instantiationService.createInstance(BufferContentTracker, _xterm);
this.element.ariaRoleDescription = localize('terminal.integrated.accessibleBuffer', 'Terminal buffer');
this.updateEditor();
@@ -40,14 +40,16 @@ export abstract class TerminalAccessibleWidget extends DisposableStore {
protected _listeners: IDisposable[] = [];
private readonly _focusedContextKey?: IContextKey<boolean>;
private readonly _focusedContextKey: IContextKey<boolean>;
private readonly _focusedLastLineContextKey: IContextKey<boolean>;
private readonly _focusTracker?: dom.IFocusTracker;
constructor(
private readonly _className: string,
protected readonly _instance: Pick<ITerminalInstance, 'shellType' | 'capabilities' | 'onDidRequestFocus' | 'resource'>,
protected readonly _xterm: Pick<IXtermTerminal, 'shellIntegration' | 'getFont'> & { raw: Terminal },
private _focusContextKey: RawContextKey<boolean> | undefined,
rawFocusContextKey: RawContextKey<boolean>,
rawFocusLastLineContextKey: RawContextKey<boolean>,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IModelService private readonly _modelService: IModelService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
@@ -87,12 +89,21 @@ export abstract class TerminalAccessibleWidget extends DisposableStore {
this._element.replaceChildren(this._editorContainer);
this._xtermElement.insertAdjacentElement('beforebegin', this._element);
if (this._focusContextKey) {
this._focusTracker = this.add(dom.trackFocus(this._editorContainer));
this._focusedContextKey = this._focusContextKey.bindTo(this._contextKeyService);
this.add(this._focusTracker.onDidFocus(() => this._focusedContextKey?.set(true)));
this.add(this._focusTracker.onDidBlur(() => this._focusedContextKey?.reset()));
}
this._focusTracker = this.add(dom.trackFocus(this._editorContainer));
this._focusedContextKey = rawFocusContextKey.bindTo(this._contextKeyService);
this._focusedLastLineContextKey = rawFocusLastLineContextKey.bindTo(this._contextKeyService);
this.add(this._focusTracker.onDidFocus(() => {
this._focusedContextKey?.set(true);
this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount());
}));
this.add(this._focusTracker.onDidBlur(() => {
this._focusedContextKey?.reset();
this._focusedLastLineContextKey?.reset();
}));
this._editorWidget.onDidChangeCursorPosition(() => {
console.log(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount());
this._focusedLastLineContextKey?.set(this._editorWidget.getSelection()?.positionLineNumber === this._editorWidget.getModel()?.getLineCount());
});
this.add(Event.runAndSubscribe(this._xterm.raw.onResize, () => this.layout()));
this.add(this._configurationService.onDidChangeConfiguration(e => {