Skip to content

Commit c8083ae

Browse files
authored
Merge branch 'main' into fix_findmatch_color
2 parents 3172a64 + 37066ba commit c8083ae

File tree

14 files changed

+383
-88
lines changed

14 files changed

+383
-88
lines changed

src/vs/editor/standalone/browser/quickInput/standaloneQuickInputService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ export class StandaloneQuickInputService implements IQuickInputService {
156156
cancel(): Promise<void> {
157157
return this.activeService.cancel();
158158
}
159+
160+
setAlignment(alignment: 'top' | 'center' | { top: number; left: number }): void {
161+
return this.activeService.setAlignment(alignment);
162+
}
159163
}
160164

161165
export class QuickInputEditorContribution implements IEditorContribution {

src/vs/platform/extensions/common/extensions.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,10 @@ export interface IWalkthroughStep {
111111
readonly title: string;
112112
readonly description: string | undefined;
113113
readonly media:
114-
| { image: string | { dark: string; light: string; hc: string }; altText: string; markdown?: never; svg?: never }
115-
| { markdown: string; image?: never; svg?: never }
116-
| { svg: string; altText: string; markdown?: never; image?: never };
114+
| { image: string | { dark: string; light: string; hc: string }; altText: string; markdown?: never; svg?: never; video?: never }
115+
| { markdown: string; image?: never; svg?: never; video?: never }
116+
| { svg: string; altText: string; markdown?: never; image?: never; video?: never }
117+
| { video: string | { dark: string; light: string; hc: string }; poster: string | { dark: string; light: string; hc: string }; altText: string; markdown?: never; image?: never; svg?: never };
117118
readonly completionEvents?: string[];
118119
/** @deprecated use `completionEvents: 'onCommand:...'` */
119120
readonly doneOn?: { command: string };

src/vs/platform/quickinput/browser/quickInput.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ export const inQuickInputContextKeyValue = 'inQuickInput';
3838
export const InQuickInputContextKey = new RawContextKey<boolean>(inQuickInputContextKeyValue, false, localize('inQuickInput', "Whether keyboard focus is inside the quick input control"));
3939
export const inQuickInputContext = ContextKeyExpr.has(inQuickInputContextKeyValue);
4040

41+
export const quickInputAlignmentContextKeyValue = 'quickInputAlignment';
42+
export const QuickInputAlignmentContextKey = new RawContextKey<'top' | 'center' | undefined>(quickInputAlignmentContextKeyValue, 'top', localize('quickInputAlignment', "The alignment of the quick input"));
43+
4144
export const quickInputTypeContextKeyValue = 'quickInputType';
4245
export const QuickInputTypeContextKey = new RawContextKey<QuickInputType>(quickInputTypeContextKeyValue, undefined, localize('quickInputType', "The type of the currently visible quick input"));
4346

src/vs/platform/quickinput/browser/quickInputController.ts

Lines changed: 141 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { isString } from '../../../base/common/types.js';
1919
import { localize } from '../../../nls.js';
2020
import { IInputBox, IInputOptions, IKeyMods, IPickOptions, IQuickInput, IQuickInputButton, IQuickNavigateConfiguration, IQuickPick, IQuickPickItem, IQuickWidget, QuickInputHideReason, QuickPickInput, QuickPickFocus } from '../common/quickInput.js';
2121
import { QuickInputBox } from './quickInputBox.js';
22-
import { QuickInputUI, Writeable, IQuickInputStyles, IQuickInputOptions, QuickPick, backButton, InputBox, Visibilities, QuickWidget, InQuickInputContextKey, QuickInputTypeContextKey, EndOfQuickInputBoxContextKey } from './quickInput.js';
22+
import { QuickInputUI, Writeable, IQuickInputStyles, IQuickInputOptions, QuickPick, backButton, InputBox, Visibilities, QuickWidget, InQuickInputContextKey, QuickInputTypeContextKey, EndOfQuickInputBoxContextKey, QuickInputAlignmentContextKey } from './quickInput.js';
2323
import { ILayoutService } from '../../layout/browser/layoutService.js';
2424
import { mainWindow } from '../../../base/browser/window.js';
2525
import { IInstantiationService } from '../../instantiation/common/instantiation.js';
@@ -331,7 +331,20 @@ export class QuickInputController extends Disposable {
331331

332332
// Drag and Drop support
333333
this.dndController = this._register(this.instantiationService.createInstance(
334-
QuickInputDragAndDropController, this._container, container, [titleBar, title, headerContainer]));
334+
QuickInputDragAndDropController,
335+
this._container,
336+
container,
337+
[
338+
{
339+
node: titleBar,
340+
includeChildren: true
341+
},
342+
{
343+
node: headerContainer,
344+
includeChildren: false
345+
}
346+
]
347+
));
335348

336349
// DnD update layout
337350
this._register(autorun(reader => {
@@ -607,6 +620,10 @@ export class QuickInputController extends Disposable {
607620
return new InputBox(ui);
608621
}
609622

623+
setAlignment(alignment: 'top' | 'center' | { top: number; left: number }): void {
624+
this.dndController?.setAlignment(alignment);
625+
}
626+
610627
createQuickWidget(): IQuickWidget {
611628
const ui = this.getUI(true);
612629
return new QuickWidget(ui);
@@ -879,16 +896,19 @@ class QuickInputDragAndDropController extends Disposable {
879896
readonly dndViewState = observableValue<{ top?: number; left?: number; done: boolean } | undefined>(this, undefined);
880897

881898
private readonly _snapThreshold = 20;
882-
private readonly _snapLineHorizontalRatio = 0.15;
899+
private readonly _snapLineHorizontalRatio = 0.25;
883900
private readonly _snapLineHorizontal: HTMLElement;
884901
private readonly _snapLineVertical1: HTMLElement;
885902
private readonly _snapLineVertical2: HTMLElement;
886903

904+
private _quickInputAlignmentContext = QuickInputAlignmentContextKey.bindTo(this._contextKeyService);
905+
887906
constructor(
888907
private _container: HTMLElement,
889908
private readonly _quickInputContainer: HTMLElement,
890-
private _quickInputDragAreas: HTMLElement[],
891-
@ILayoutService private readonly _layoutService: ILayoutService
909+
private _quickInputDragAreas: { node: HTMLElement; includeChildren: boolean }[],
910+
@ILayoutService private readonly _layoutService: ILayoutService,
911+
@IContextKeyService private readonly _contextKeyService: IContextKeyService
892912
) {
893913
super();
894914

@@ -909,87 +929,138 @@ class QuickInputDragAndDropController extends Disposable {
909929
dom.append(this._container, this._snapLineVertical2);
910930
}
911931

932+
setAlignment(alignment: 'top' | 'center' | { top: number; left: number }, done = true): void {
933+
if (alignment === 'top') {
934+
this.dndViewState.set({
935+
top: this._getTopSnapValue() / this._container.clientHeight,
936+
left: (this._getCenterXSnapValue() + (this._quickInputContainer.clientWidth / 2)) / this._container.clientWidth,
937+
done
938+
}, undefined);
939+
this._quickInputAlignmentContext.set('top');
940+
} else if (alignment === 'center') {
941+
this.dndViewState.set({
942+
top: this._getCenterYSnapValue() / this._container.clientHeight,
943+
left: (this._getCenterXSnapValue() + (this._quickInputContainer.clientWidth / 2)) / this._container.clientWidth,
944+
done
945+
}, undefined);
946+
this._quickInputAlignmentContext.set('center');
947+
} else {
948+
this.dndViewState.set({ top: alignment.top, left: alignment.left, done }, undefined);
949+
this._quickInputAlignmentContext.set(undefined);
950+
}
951+
}
952+
912953
private registerMouseListeners(): void {
913-
for (const dragArea of this._quickInputDragAreas) {
914-
let top: number | undefined;
915-
let left: number | undefined;
954+
let top: number | undefined;
955+
let left: number | undefined;
956+
const dragArea = this._quickInputContainer;
957+
958+
// Double click
959+
this._register(dom.addDisposableGenericMouseUpListener(dragArea, (event: MouseEvent) => {
960+
const originEvent = new StandardMouseEvent(dom.getWindow(dragArea), event);
961+
if (originEvent.detail !== 2) {
962+
return;
963+
}
916964

917-
// Double click
918-
this._register(dom.addDisposableGenericMouseUpListener(dragArea, (event: MouseEvent) => {
919-
const originEvent = new StandardMouseEvent(dom.getWindow(dragArea), event);
965+
// Ignore event if the target is not the drag area
966+
if (!this._quickInputDragAreas.some(({ node, includeChildren }) => includeChildren ? dom.isAncestor(originEvent.target as HTMLElement, node) : originEvent.target === node)) {
967+
return;
968+
}
920969

921-
// Ignore event if the target is not the drag area
922-
if (originEvent.target !== dragArea) {
923-
return;
924-
}
970+
top = undefined;
971+
left = undefined;
925972

926-
if (originEvent.detail === 2) {
927-
top = undefined;
928-
left = undefined;
973+
this.dndViewState.set({ top, left, done: true }, undefined);
974+
}));
929975

930-
this.dndViewState.set({ top, left, done: true }, undefined);
931-
}
932-
}));
976+
// Mouse down
977+
this._register(dom.addDisposableGenericMouseDownListener(dragArea, (e: MouseEvent) => {
978+
const activeWindow = dom.getWindow(this._layoutService.activeContainer);
979+
const originEvent = new StandardMouseEvent(activeWindow, e);
933980

934-
// Mouse down
935-
this._register(dom.addDisposableGenericMouseDownListener(dragArea, (e: MouseEvent) => {
936-
const activeWindow = dom.getWindow(this._layoutService.activeContainer);
937-
const originEvent = new StandardMouseEvent(activeWindow, e);
981+
// Ignore event if the target is not the drag area
982+
if (!this._quickInputDragAreas.some(({ node, includeChildren }) => includeChildren ? dom.isAncestor(originEvent.target as HTMLElement, node) : originEvent.target === node)) {
983+
return;
984+
}
938985

939-
// Ignore event if the target is not the drag area
940-
if (originEvent.target !== dragArea) {
941-
return;
986+
// Mouse position offset relative to dragArea
987+
const dragAreaRect = this._quickInputContainer.getBoundingClientRect();
988+
const dragOffsetX = originEvent.browserEvent.clientX - dragAreaRect.left;
989+
const dragOffsetY = originEvent.browserEvent.clientY - dragAreaRect.top;
990+
991+
// Snap lines
992+
let isMovingQuickInput = false;
993+
const snapCoordinateYTop = this._getTopSnapValue();
994+
const snapCoordinateY = this._getCenterYSnapValue();
995+
const snapCoordinateX = this._getCenterXSnapValue();
996+
997+
// Mouse move
998+
const mouseMoveListener = dom.addDisposableGenericMouseMoveListener(activeWindow, (e: MouseEvent) => {
999+
const mouseMoveEvent = new StandardMouseEvent(activeWindow, e);
1000+
mouseMoveEvent.preventDefault();
1001+
1002+
if (!isMovingQuickInput) {
1003+
this._showSnapLines(snapCoordinateY, snapCoordinateX);
1004+
isMovingQuickInput = true;
9421005
}
9431006

944-
// Mouse position offset relative to dragArea
945-
const dragAreaRect = this._quickInputContainer.getBoundingClientRect();
946-
const dragOffsetX = originEvent.browserEvent.clientX - dragAreaRect.left;
947-
const dragOffsetY = originEvent.browserEvent.clientY - dragAreaRect.top;
948-
949-
// Snap lines
950-
let snapLinesVisible = false;
951-
const snapCoordinateYTop = this._layoutService.activeContainerOffset.quickPickTop;
952-
const snapCoordinateY = Math.round(this._container.clientHeight * this._snapLineHorizontalRatio);
953-
const snapCoordinateX = Math.round(this._container.clientWidth / 2) - Math.round(this._quickInputContainer.clientWidth / 2);
954-
955-
// Mouse move
956-
const mouseMoveListener = dom.addDisposableGenericMouseMoveListener(activeWindow, (e: MouseEvent) => {
957-
const mouseMoveEvent = new StandardMouseEvent(activeWindow, e);
958-
mouseMoveEvent.preventDefault();
959-
960-
if (!snapLinesVisible) {
961-
this._showSnapLines(snapCoordinateY, snapCoordinateX);
962-
snapLinesVisible = true;
1007+
let topCoordinate = e.clientY - dragOffsetY;
1008+
// Make sure the quick input is not moved outside the container
1009+
topCoordinate = Math.max(0, Math.min(topCoordinate, this._container.clientHeight - this._quickInputContainer.clientHeight));
1010+
const snappingToTop = Math.abs(topCoordinate - snapCoordinateYTop) < this._snapThreshold;
1011+
topCoordinate = snappingToTop ? snapCoordinateYTop : topCoordinate;
1012+
const snappingToCenter = Math.abs(topCoordinate - snapCoordinateY) < this._snapThreshold;
1013+
topCoordinate = snappingToCenter ? snapCoordinateY : topCoordinate;
1014+
top = topCoordinate / this._container.clientHeight;
1015+
1016+
let leftCoordinate = e.clientX - dragOffsetX;
1017+
// Make sure the quick input is not moved outside the container
1018+
leftCoordinate = Math.max(0, Math.min(leftCoordinate, this._container.clientWidth - this._quickInputContainer.clientWidth));
1019+
const snappingToCenterX = Math.abs(leftCoordinate - snapCoordinateX) < this._snapThreshold;
1020+
leftCoordinate = snappingToCenterX ? snapCoordinateX : leftCoordinate;
1021+
left = (leftCoordinate + (this._quickInputContainer.clientWidth / 2)) / this._container.clientWidth;
1022+
1023+
this.dndViewState.set({ top, left, done: false }, undefined);
1024+
if (snappingToCenterX) {
1025+
if (snappingToTop) {
1026+
this._quickInputAlignmentContext.set('top');
1027+
return;
1028+
} else if (snappingToCenter) {
1029+
this._quickInputAlignmentContext.set('center');
1030+
return;
9631031
}
1032+
}
1033+
this._quickInputAlignmentContext.set(undefined);
1034+
});
9641035

965-
let topCoordinate = e.clientY - dragOffsetY;
966-
topCoordinate = Math.max(0, Math.min(topCoordinate, this._container.clientHeight - this._quickInputContainer.clientHeight));
967-
topCoordinate = Math.abs(topCoordinate - snapCoordinateYTop) < this._snapThreshold ? snapCoordinateYTop : topCoordinate;
968-
topCoordinate = Math.abs(topCoordinate - snapCoordinateY) < this._snapThreshold ? snapCoordinateY : topCoordinate;
969-
top = topCoordinate / this._container.clientHeight;
970-
971-
let leftCoordinate = e.clientX - dragOffsetX;
972-
leftCoordinate = Math.max(0, Math.min(leftCoordinate, this._container.clientWidth - this._quickInputContainer.clientWidth));
973-
leftCoordinate = Math.abs(leftCoordinate - snapCoordinateX) < this._snapThreshold ? snapCoordinateX : leftCoordinate;
974-
left = (leftCoordinate + (this._quickInputContainer.clientWidth / 2)) / this._container.clientWidth;
975-
976-
this.dndViewState.set({ top, left, done: false }, undefined);
977-
});
978-
979-
// Mouse up
980-
const mouseUpListener = dom.addDisposableGenericMouseUpListener(activeWindow, (e: MouseEvent) => {
1036+
// Mouse up
1037+
const mouseUpListener = dom.addDisposableGenericMouseUpListener(activeWindow, (e: MouseEvent) => {
1038+
if (isMovingQuickInput) {
9811039
// Hide snaplines
9821040
this._hideSnapLines();
9831041

9841042
// Save position
985-
this.dndViewState.set({ top, left, done: true }, undefined);
1043+
const state = this.dndViewState.get();
1044+
this.dndViewState.set({ top: state?.top, left: state?.left, done: true }, undefined);
1045+
}
9861046

987-
// Dispose listeners
988-
mouseMoveListener.dispose();
989-
mouseUpListener.dispose();
990-
});
991-
}));
992-
}
1047+
// Dispose listeners
1048+
mouseMoveListener.dispose();
1049+
mouseUpListener.dispose();
1050+
});
1051+
}));
1052+
}
1053+
1054+
private _getTopSnapValue() {
1055+
return this._layoutService.activeContainerOffset.quickPickTop;
1056+
}
1057+
1058+
private _getCenterYSnapValue() {
1059+
return Math.round(this._container.clientHeight * this._snapLineHorizontalRatio);
1060+
}
1061+
1062+
private _getCenterXSnapValue() {
1063+
return Math.round(this._container.clientWidth / 2) - Math.round(this._quickInputContainer.clientWidth / 2);
9931064
}
9941065

9951066
private _showSnapLines(horizontal: number, vertical: number) {

src/vs/platform/quickinput/browser/quickInputService.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ export class QuickInputService extends Themable implements IQuickInputService {
195195
return this.controller.cancel();
196196
}
197197

198+
setAlignment(alignment: 'top' | 'center' | { top: number; left: number }): void {
199+
this.controller.setAlignment(alignment);
200+
}
201+
198202
override updateStyles() {
199203
if (this.hasController) {
200204
this.controller.applyStyles(this.computeStyles());

src/vs/platform/quickinput/common/quickInput.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,4 +931,10 @@ export interface IQuickInputService {
931931
* The current quick pick that is visible. Undefined if none is open.
932932
*/
933933
currentQuickInput: IQuickInput | undefined;
934+
935+
/**
936+
* Set the alignment of the quick input.
937+
* @param alignment either a preset or a custom alignment
938+
*/
939+
setAlignment(alignment: 'top' | 'center' | { top: number; left: number }): void;
934940
}

0 commit comments

Comments
 (0)