Accept in background using a Command (#211896)

More progress towards https://github.com/microsoft/vscode/issues/98479
This commit is contained in:
Tyler James Leonhardt 2024-05-02 19:39:34 -07:00 committed by GitHub
parent da926b795c
commit 2bdbf82fe7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 24 deletions

View file

@ -42,6 +42,10 @@ export const inQuickInputContext = ContextKeyExpr.has(inQuickInputContextKeyValu
export const quickInputTypeContextKeyValue = 'quickInputType';
export const QuickInputTypeContextKey = new RawContextKey<QuickInputType>(quickInputTypeContextKeyValue, undefined, localize('quickInputType', "The type of the currently visible quick input"));
export const endOfQuickInputBoxContextKeyValue = 'cursorAtEndOfQuickInputBox';
export const EndOfQuickInputBoxContextKey = new RawContextKey<boolean>(endOfQuickInputBoxContextKeyValue, false, localize('cursorAtEndOfQuickInputBox', "Whether the cursor in the quick input is at the end of the input box"));
export const endOfQuickInputBoxContext = ContextKeyExpr.has(endOfQuickInputBoxContextKeyValue);
export interface IQuickInputOptions {
idPrefix: string;
container: HTMLElement;
@ -841,27 +845,6 @@ export class QuickPick<T extends IQuickPickItem> extends QuickInput implements I
this.ui.inputBox.onDidChange(value => {
this.doSetValue(value, true /* skip update since this originates from the UI */);
}));
// Keybindings for the input box or list if there is no input box
this.visibleDisposables.add((this._hideInput ? this.ui.list : this.ui.inputBox).onKeyDown((event: KeyboardEvent | StandardKeyboardEvent) => {
switch (event.keyCode) {
case KeyCode.RightArrow:
if (!this._canAcceptInBackground) {
return; // needs to be enabled
}
if (!this.ui.inputBox.isSelectionAtEnd()) {
return; // ensure input box selection at end
}
if (this.activeItems[0]) {
this._selectedItems = [this.activeItems[0]];
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
this.handleAccept(true);
}
break;
}
}));
this.visibleDisposables.add(this.ui.onDidAccept(() => {
if (this.canSelectMany) {
// if there are no checked elements, it means that an onDidChangeSelection never fired to overwrite
@ -1127,6 +1110,18 @@ export class QuickPick<T extends IQuickPickItem> extends QuickInput implements I
this.ui.list.domFocus();
}
}
accept(inBackground?: boolean | undefined): void {
if (inBackground && !this._canAcceptInBackground) {
return; // needs to be enabled
}
if (this.activeItems[0]) {
this._selectedItems = [this.activeItems[0]];
this.onDidChangeSelectionEmitter.fire(this.selectedItems);
this.handleAccept(inBackground ?? false);
}
}
}
export class InputBox extends QuickInput implements IInputBox {

View file

@ -9,8 +9,9 @@ import { PartialExcept } from 'vs/base/common/types';
import { localize } from 'vs/nls';
import { ICommandHandler } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { InputFocusedContext } from 'vs/platform/contextkey/common/contextkeys';
import { ICommandAndKeybindingRule, KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { inQuickInputContext, quickInputTypeContextKeyValue } from 'vs/platform/quickinput/browser/quickInput';
import { endOfQuickInputBoxContext, inQuickInputContext, quickInputTypeContextKeyValue } from 'vs/platform/quickinput/browser/quickInput';
import { IQuickInputService, IQuickPick, QuickInputType, QuickPickFocus } from 'vs/platform/quickinput/common/quickInput';
const defaultCommandAndKeybindingRule = {
@ -178,3 +179,22 @@ if (isMacintosh) {
}
//#endregion
//#region Accept
registerQuickPickCommandAndKeybindingRule(
{
id: 'quickInput.acceptInBackground',
// If we are in the quick pick but the input box is not focused or our cursor is at the end of the input box
when: ContextKeyExpr.and(defaultCommandAndKeybindingRule.when, ContextKeyExpr.or(InputFocusedContext.negate(), endOfQuickInputBoxContext)),
primary: KeyCode.RightArrow,
// Need a little extra weight to ensure this keybinding is preferred over the default cmd+alt+right arrow keybinding
// https://github.com/microsoft/vscode/blob/1451e4fbbbf074a4355cc537c35b547b80ce1c52/src/vs/workbench/browser/parts/editor/editorActions.ts#L1178-L1195
weight: KeybindingWeight.WorkbenchContrib + 50,
handler: (accessor) => {
const currentQuickPick = accessor.get(IQuickInputService).currentQuickInput as IQuickPick<any>;
currentQuickPick?.accept(true);
},
},
{ withAltMod: true, withCtrlMod: true, withCmdMod: true }
);

View file

@ -18,7 +18,7 @@ import { isString } from 'vs/base/common/types';
import { localize } from 'vs/nls';
import { IInputBox, IInputOptions, IKeyMods, IPickOptions, IQuickInput, IQuickInputButton, IQuickNavigateConfiguration, IQuickPick, IQuickPickItem, IQuickWidget, QuickInputHideReason, QuickPickInput } from 'vs/platform/quickinput/common/quickInput';
import { QuickInputBox } from 'vs/platform/quickinput/browser/quickInputBox';
import { QuickInputUI, Writeable, IQuickInputStyles, IQuickInputOptions, QuickPick, backButton, InputBox, Visibilities, QuickWidget, InQuickInputContextKey, QuickInputTypeContextKey } from 'vs/platform/quickinput/browser/quickInput';
import { QuickInputUI, Writeable, IQuickInputStyles, IQuickInputOptions, QuickPick, backButton, InputBox, Visibilities, QuickWidget, InQuickInputContextKey, QuickInputTypeContextKey, EndOfQuickInputBoxContextKey } from 'vs/platform/quickinput/browser/quickInput';
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
import { mainWindow } from 'vs/base/browser/window';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@ -60,6 +60,7 @@ export class QuickInputController extends Disposable {
private readonly inQuickInputContext = InQuickInputContextKey.bindTo(this.contextKeyService);
private readonly quickInputTypeContext = QuickInputTypeContextKey.bindTo(this.contextKeyService);
private readonly endOfQuickInputBoxContext = EndOfQuickInputBoxContextKey.bindTo(this.contextKeyService);
constructor(
private options: IQuickInputOptions,
@ -212,8 +213,15 @@ export class QuickInputController extends Disposable {
const focusTracker = dom.trackFocus(container);
this._register(focusTracker);
this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, e => {
const ui = this.getUI();
if (dom.isAncestor(e.relatedTarget as HTMLElement, ui.inputContainer)) {
const value = ui.inputBox.isSelectionAtEnd();
if (this.endOfQuickInputBoxContext.get() !== value) {
this.endOfQuickInputBoxContext.set(value);
}
}
// Ignore focus events within container
if (dom.isAncestor(e.relatedTarget as HTMLElement, container)) {
if (dom.isAncestor(e.relatedTarget as HTMLElement, ui.container)) {
return;
}
this.inQuickInputContext.set(true);
@ -224,8 +232,15 @@ export class QuickInputController extends Disposable {
this.hide(QuickInputHideReason.Blur);
}
this.inQuickInputContext.set(false);
this.endOfQuickInputBoxContext.set(false);
this.previousFocusElement = undefined;
}));
this._register(inputBox.onKeyDown(_ => {
const value = this.getUI().inputBox.isSelectionAtEnd();
if (this.endOfQuickInputBoxContext.get() !== value) {
this.endOfQuickInputBoxContext.set(value);
}
}));
this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, (e: FocusEvent) => {
inputBox.setFocus();
}));

View file

@ -629,6 +629,12 @@ export interface IQuickPick<T extends IQuickPickItem> extends IQuickInput {
* @param focus The focus behavior.
*/
focus(focus: QuickPickFocus): void;
/**
* Programmatically accepts an item. Used internally for keyboard navigation.
* @param inBackground Whether you are accepting an item in the background and keeping the picker open.
*/
accept(inBackground?: boolean): void;
}
/**