From ba5b9f7c88f96a5703a4691f826293cd1b09bf48 Mon Sep 17 00:00:00 2001 From: jeanp413 Date: Mon, 31 May 2021 10:31:45 -0500 Subject: [PATCH] Fixes #124928 --- .../terminal/browser/media/terminal.css | 18 +++++--- .../contrib/terminal/browser/terminal.ts | 4 +- .../terminal/browser/terminalInstance.ts | 41 ++++++++++++++----- .../terminal/browser/terminalService.ts | 4 +- .../terminal/browser/terminalTabsList.ts | 11 +++-- 5 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index 43ec8b83b290f..eddfc9db45bdd 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -16,7 +16,8 @@ .monaco-workbench .pane-body.integrated-terminal .terminal-outer-container, .monaco-workbench .pane-body.integrated-terminal .terminal-groups-container, -.monaco-workbench .pane-body.integrated-terminal .terminal-group { +.monaco-workbench .pane-body.integrated-terminal .terminal-group, +.monaco-workbench .pane-body.integrated-terminal .terminal-split-pane { height: 100%; } @@ -309,14 +310,21 @@ position: absolute; left: 0; right: 0; - height: 100%; + top: 0; + bottom: 0; pointer-events: none; opacity: 0; /* hidden initially */ - transition: left 70ms ease-out, right 70ms ease-out, opacity 150ms ease-out; + transition: left 70ms ease-out, right 70ms ease-out, top 70ms ease-out, bottom 70ms ease-out, opacity 150ms ease-out; } -.monaco-workbench .pane-body.integrated-terminal .terminal-drop-overlay.drop-left { +.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.horizontal .terminal-drop-overlay.drop-before { right: 50%; } -.monaco-workbench .pane-body.integrated-terminal .terminal-drop-overlay.drop-right { +.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.horizontal .terminal-drop-overlay.drop-after { left: 50% } +.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.vertical .terminal-drop-overlay.drop-before { + bottom: 50%; +} +.monaco-workbench .pane-body.integrated-terminal .terminal-group > .monaco-split-view2.vertical .terminal-drop-overlay.drop-after { + top: 50%; +} diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 84856ddaff547..3f471cfbb7944 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -162,7 +162,7 @@ export interface ITerminalService { * Moves a terminal instance's group to the target instance group's position. */ moveGroup(source: ITerminalInstance, target: ITerminalInstance): void; - moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'left' | 'right'): void; + moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'before' | 'after'): void; /** * Perform an action with the active terminal instance, if the terminal does @@ -629,7 +629,7 @@ export interface ITerminalInstance { export interface IRequestAddInstanceToGroupEvent { uri: URI; - side: 'left' | 'right' + side: 'before' | 'after' } export const enum LinuxDistro { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index acef7a71f9085..6f46df4b047da 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -58,8 +58,10 @@ import { isMacintosh, isWindows, OperatingSystem, OS } from 'vs/base/common/plat import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; import { DataTransfers } from 'vs/base/browser/dnd'; -import { DragAndDropObserver, IDragAndDropObserverCallbacks } from 'vs/workbench/browser/dnd'; +import { containsDragType, DragAndDropObserver, IDragAndDropObserverCallbacks } from 'vs/workbench/browser/dnd'; import { getColorClass } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; +import { IWorkbenchLayoutService, Position } from 'vs/workbench/services/layout/browser/layoutService'; +import { Orientation } from 'vs/base/browser/ui/sash/sash'; // How long in milliseconds should an average frame take to render for a notification to appear // which suggests the fallback DOM-based renderer @@ -816,14 +818,14 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _initDragAndDrop(container: HTMLElement) { this._dndObserver?.dispose(); - const dndController = new TerminalInstanceDragAndDropController(container); + const dndController = this._instantiationService.createInstance(TerminalInstanceDragAndDropController, container); dndController.onDropTerminal(e => this._onRequestAddInstanceToGroup.fire(e)); dndController.onDropFile(async path => { const preparedPath = await this._terminalInstanceService.preparePathForTerminalAsync(path, this.shellLaunchConfig.executable, this.title, this.shellType, this.isRemote); this.sendText(preparedPath, false); this.focus(); }); - this._dndObserver = new DragAndDropObserver(container.parentElement!, dndController); + this._dndObserver = new DragAndDropObserver(container, dndController); } private async _measureRenderTime(): Promise { @@ -1922,7 +1924,9 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA get onDropTerminal(): Event { return this._onDropTerminal.event; } constructor( - private readonly _container: HTMLElement + private readonly _container: HTMLElement, + @IWorkbenchLayoutService private readonly _layoutService: IWorkbenchLayoutService, + @IViewDescriptorService private readonly _viewDescriptorService: IViewDescriptorService, ) { super(); this._register(toDisposable(() => this._clearDropOverlay())); @@ -1936,6 +1940,10 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA } onDragEnter(e: DragEvent) { + if (!containsDragType(e, DataTransfers.FILES, DataTransfers.RESOURCES, 'terminals')) { + return; + } + if (!this._dropOverlay) { this._dropOverlay = document.createElement('div'); this._dropOverlay.classList.add('terminal-drop-overlay'); @@ -1946,8 +1954,8 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA // Dragging terminals if (types.includes('terminals')) { const side = this._getDropSide(e); - this._dropOverlay.classList.toggle('drop-left', side === 'left'); - this._dropOverlay.classList.toggle('drop-right', side === 'right'); + this._dropOverlay.classList.toggle('drop-before', side === 'before'); + this._dropOverlay.classList.toggle('drop-after', side === 'after'); } if (!this._dropOverlay.parentElement) { @@ -1972,8 +1980,8 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA // Dragging terminals if (types.includes('terminals')) { const side = this._getDropSide(e); - this._dropOverlay.classList.toggle('drop-left', side === 'left'); - this._dropOverlay.classList.toggle('drop-right', side === 'right'); + this._dropOverlay.classList.toggle('drop-before', side === 'before'); + this._dropOverlay.classList.toggle('drop-after', side === 'after'); } this._dropOverlay.style.opacity = '1'; @@ -2012,13 +2020,24 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA this._onDropFile.fire(path); } - private _getDropSide(e: DragEvent): 'left' | 'right' { + private _getDropSide(e: DragEvent): 'before' | 'after' { const target = this._container; if (!target) { - return 'right'; + return 'after'; } + const rect = target.getBoundingClientRect(); - return e.clientX - rect.left < rect.width / 2 ? 'left' : 'right'; + return this._getViewOrientation() === Orientation.HORIZONTAL + ? (e.clientX - rect.left < rect.width / 2 ? 'before' : 'after') + : (e.clientY - rect.top < rect.height / 2 ? 'before' : 'after'); + } + + private _getViewOrientation(): Orientation { + const panelPosition = this._layoutService.getPanelPosition(); + const terminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID); + return terminalLocation === ViewContainerLocation.Panel && panelPosition === Position.BOTTOM + ? Orientation.HORIZONTAL + : Orientation.VERTICAL; } } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index 3047975e1f3fb..f8dc7c199fb4c 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -732,7 +732,7 @@ export class TerminalService implements ITerminalService { this._onInstancesChanged.fire(); } - moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'left' | 'right'): void { + moveInstance(source: ITerminalInstance, target: ITerminalInstance, side: 'before' | 'after'): void { const sourceGroup = this.getGroupForInstance(source); const targetGroup = this.getGroupForInstance(target); if (!sourceGroup || !targetGroup) { @@ -747,7 +747,7 @@ export class TerminalService implements ITerminalService { } // Rearrange within the target group - const index = targetGroup.terminalInstances.indexOf(target) + (side === 'right' ? 1 : 0); + const index = targetGroup.terminalInstances.indexOf(target) + (side === 'after' ? 1 : 0); targetGroup.moveInstance(source, index); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts index 6b9f9e5e68367..ce84d5b4f84b6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts @@ -30,7 +30,7 @@ import { Disposable, DisposableStore, dispose, IDisposable, toDisposable } from import { IListDragAndDrop, IListDragOverReaction, IListRenderer, ListDragOverEffect } from 'vs/base/browser/ui/list/list'; import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; import { disposableTimeout } from 'vs/base/common/async'; -import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; +import { ElementsDragAndDropData, NativeDragAndDropData } from 'vs/base/browser/ui/list/listView'; import { URI } from 'vs/base/common/uri'; import { getColorClass, getIconId, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon'; import { Schemas } from 'vs/base/common/network'; @@ -41,6 +41,7 @@ import { once } from 'vs/base/common/functional'; import { attachInputBoxStyler } from 'vs/platform/theme/common/styler'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; +import { containsDragType } from 'vs/workbench/browser/dnd'; const $ = DOM.$; @@ -537,7 +538,11 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop { } onDragOver(data: IDragAndDropData, targetInstance: ITerminalInstance | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | IListDragOverReaction { - let result = true; + if (data instanceof NativeDragAndDropData) { + if (!containsDragType(originalEvent, DataTransfers.FILES, DataTransfers.RESOURCES)) { + return false; + } + } const didChangeAutoFocusInstance = this._autoFocusInstance !== targetInstance; if (didChangeAutoFocusInstance) { @@ -546,7 +551,7 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop { } if (!targetInstance) { - return result; + return data instanceof ElementsDragAndDropData; } if (didChangeAutoFocusInstance) {