Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes terminal drop overlay moves horizontally instead of vertically when pane is on the side #124985

Merged
merged 2 commits into from
Jun 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions src/vs/workbench/contrib/terminal/browser/media/terminal.css
Original file line number Diff line number Diff line change
Expand Up @@ -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%;
}

Expand Down Expand Up @@ -314,14 +315,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%;
}
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -631,7 +631,7 @@ export interface ITerminalInstance {

export interface IRequestAddInstanceToGroupEvent {
uri: URI;
side: 'left' | 'right'
side: 'before' | 'after'
}

export const enum LinuxDistro {
Expand Down
41 changes: 30 additions & 11 deletions src/vs/workbench/contrib/terminal/browser/terminalInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -832,14 +834,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<void> {
Expand Down Expand Up @@ -1936,7 +1938,9 @@ class TerminalInstanceDragAndDropController extends Disposable implements IDragA
get onDropTerminal(): Event<IRequestAddInstanceToGroupEvent> { 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()));
Expand All @@ -1950,6 +1954,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');
Expand All @@ -1960,8 +1968,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) {
Expand All @@ -1986,8 +1994,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';
Expand Down Expand Up @@ -2026,13 +2034,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;
Comment on lines +2049 to +2054
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to copy this logic from TerminalGroup as I cannot use TerminalService.onPanelOrientationChanged to avoid a cyclic dependency

}
}

Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/terminal/browser/terminalService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,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) {
Expand All @@ -757,7 +757,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);
}

Expand Down
11 changes: 8 additions & 3 deletions src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';

const $ = DOM.$;
Expand Down Expand Up @@ -548,7 +549,11 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop<ITerminalInstance> {
}

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) {
Expand All @@ -557,7 +562,7 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop<ITerminalInstance> {
}

if (!targetInstance) {
return result;
return data instanceof ElementsDragAndDropData;
}

if (didChangeAutoFocusInstance) {
Expand Down