diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts index d2fa1bd3ba8..a59a09e21f1 100644 --- a/src/vs/base/browser/dom.ts +++ b/src/vs/base/browser/dom.ts @@ -1702,8 +1702,7 @@ export interface IDragAndDropObserverCallbacks { readonly onDragLeave: (e: DragEvent) => void; readonly onDrop: (e: DragEvent) => void; readonly onDragEnd: (e: DragEvent) => void; - - readonly onDragOver?: (e: DragEvent) => void; + readonly onDragOver?: (e: DragEvent, dragDuration: number) => void; } export class DragAndDropObserver extends Disposable { @@ -1714,6 +1713,9 @@ export class DragAndDropObserver extends Disposable { // repeadedly. private counter: number = 0; + // Allows to measure the duration of the drag operation. + private dragStartTime = 0; + constructor(private readonly element: HTMLElement, private readonly callbacks: IDragAndDropObserverCallbacks) { super(); @@ -1723,6 +1725,7 @@ export class DragAndDropObserver extends Disposable { private registerListeners(): void { this._register(addDisposableListener(this.element, EventType.DRAG_ENTER, (e: DragEvent) => { this.counter++; + this.dragStartTime = e.timeStamp; this.callbacks.onDragEnter(e); })); @@ -1731,7 +1734,7 @@ export class DragAndDropObserver extends Disposable { e.preventDefault(); // needed so that the drop event fires (https://stackoverflow.com/questions/21339924/drop-event-not-firing-in-chrome) if (this.callbacks.onDragOver) { - this.callbacks.onDragOver(e); + this.callbacks.onDragOver(e, e.timeStamp - this.dragStartTime); } })); @@ -1739,17 +1742,23 @@ export class DragAndDropObserver extends Disposable { this.counter--; if (this.counter === 0) { + this.dragStartTime = 0; + this.callbacks.onDragLeave(e); } })); this._register(addDisposableListener(this.element, EventType.DRAG_END, (e: DragEvent) => { this.counter = 0; + this.dragStartTime = 0; + this.callbacks.onDragEnd(e); })); this._register(addDisposableListener(this.element, EventType.DROP, (e: DragEvent) => { this.counter = 0; + this.dragStartTime = 0; + this.callbacks.onDrop(e); })); } diff --git a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts index 6d834b41807..386e13b2e0b 100644 --- a/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts +++ b/src/vs/workbench/browser/parts/editor/tabsTitleControl.ts @@ -97,6 +97,8 @@ export class TabsTitleControl extends TitleControl { private static readonly TAB_HEIGHT = 35; + private static readonly DRAG_OVER_OPEN_TAB_THRESHOLD = 1500; + private static readonly MOUSE_WHEEL_EVENT_THRESHOLD = 150; private static readonly MOUSE_WHEEL_DISTANCE_THRESHOLD = 1.5; @@ -898,6 +900,15 @@ export class TabsTitleControl extends TitleControl { this.updateDropFeedback(tab, true, index); }, + onDragOver: (_, dragDuration) => { + if (dragDuration >= TabsTitleControl.DRAG_OVER_OPEN_TAB_THRESHOLD) { + const draggedOverTab = this.group.getEditorByIndex(index); + if (draggedOverTab && this.group.activeEditor !== draggedOverTab) { + this.group.openEditor(draggedOverTab, { preserveFocus: true }); + } + } + }, + onDragLeave: () => { tab.classList.remove('dragged-over'); this.updateDropFeedback(tab, false, index);