Skip to content

Commit c1d9161

Browse files
authored
Merge pull request microsoft#146249 from microsoft/tyriar/129954
Remove terminal knowledge from dnd component
2 parents 2381cae + c241bd3 commit c1d9161

File tree

9 files changed

+113
-42
lines changed

9 files changed

+113
-42
lines changed

src/vs/base/browser/dnd.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,7 @@ export const DataTransfers = {
7171
/**
7272
* Typically transfer type for copy/paste transfers.
7373
*/
74-
TEXT: Mimes.text,
75-
76-
/**
77-
* Application specific terminal transfer type.
78-
*/
79-
TERMINALS: 'Terminals'
74+
TEXT: Mimes.text
8075
};
8176

8277
export function applyDragImage(event: DragEvent, label: string | null, clazz: string): void {

src/vs/workbench/browser/dnd.ts

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import { ITreeDragOverReaction } from 'vs/base/browser/ui/tree/tree';
4141
import { WebFileSystemAccess } from 'vs/platform/files/browser/webFileSystemAccess';
4242
import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystemProvider';
4343
import { DeferredPromise } from 'vs/base/common/async';
44+
import { Registry } from 'vs/platform/registry/common/platform';
4445

4546
//#region Editor / Resources DND
4647

@@ -132,19 +133,6 @@ export async function extractEditorsDropData(accessor: ServicesAccessor, e: Drag
132133
}
133134
}
134135

135-
// Check for terminals transfer
136-
const terminals = e.dataTransfer.getData(DataTransfers.TERMINALS);
137-
if (terminals) {
138-
try {
139-
const terminalEditors: string[] = JSON.parse(terminals);
140-
for (const terminalEditor of terminalEditors) {
141-
editors.push({ resource: URI.parse(terminalEditor) });
142-
}
143-
} catch (error) {
144-
// Invalid transfer
145-
}
146-
}
147-
148136
// Web: Check for file transfer
149137
if (isWeb && containsDragType(e, DataTransfers.FILES)) {
150138
const files = e.dataTransfer.items;
@@ -156,6 +144,19 @@ export async function extractEditorsDropData(accessor: ServicesAccessor, e: Drag
156144
}
157145
}
158146
}
147+
148+
// Workbench contributions
149+
const contributions = Registry.as<IDragAndDropContributionRegistry>(Extensions.DragAndDropContribution).getAll();
150+
for (const contribution of contributions) {
151+
const data = e.dataTransfer.getData(contribution.dataFormatKey);
152+
if (data) {
153+
try {
154+
editors.push(...contribution.getEditorInputs(data));
155+
} catch (error) {
156+
// Invalid transfer
157+
}
158+
}
159+
}
159160
}
160161

161162
return editors;
@@ -502,10 +503,10 @@ export function fillEditorsDragData(accessor: ServicesAccessor, resourcesOrEdito
502503
event.dataTransfer.setData(DataTransfers.RESOURCES, JSON.stringify(files.map(({ resource }) => resource.toString())));
503504
}
504505

505-
// Terminal URI
506-
const terminalResources = resources.filter(({ resource }) => resource.scheme === Schemas.vscodeTerminal);
507-
if (terminalResources.length) {
508-
event.dataTransfer.setData(DataTransfers.TERMINALS, JSON.stringify(terminalResources.map(({ resource }) => resource.toString())));
506+
// Contributions
507+
const contributions = Registry.as<IDragAndDropContributionRegistry>(Extensions.DragAndDropContribution).getAll();
508+
for (const contribution of contributions) {
509+
contribution.setData(resources, event);
509510
}
510511

511512
// Editors: enables cross window DND of editors
@@ -590,6 +591,49 @@ export function fillEditorsDragData(accessor: ServicesAccessor, resourcesOrEdito
590591

591592
//#endregion
592593

594+
//#region DND contributions
595+
596+
export interface IDragAndDropContributionRegistry {
597+
/**
598+
* Registers a drag and drop contribution.
599+
*/
600+
register(contribution: IDragAndDropContribution): void;
601+
602+
/**
603+
* Returns all registered drag and drop contributions.
604+
*/
605+
getAll(): IterableIterator<IDragAndDropContribution>;
606+
}
607+
608+
export interface IDragAndDropContribution {
609+
readonly dataFormatKey: string;
610+
getEditorInputs(data: string): IDraggedResourceEditorInput[];
611+
setData(resources: IResourceStat[], event: DragMouseEvent | DragEvent): void;
612+
}
613+
614+
class DragAndDropContributionRegistry implements IDragAndDropContributionRegistry {
615+
private readonly _contributions = new Map<string, IDragAndDropContribution>();
616+
617+
register(contribution: IDragAndDropContribution): void {
618+
if (this._contributions.has(contribution.dataFormatKey)) {
619+
throw new Error(`A drag and drop contributiont with key '${contribution.dataFormatKey}' was already registered.`);
620+
}
621+
this._contributions.set(contribution.dataFormatKey, contribution);
622+
}
623+
624+
getAll(): IterableIterator<IDragAndDropContribution> {
625+
return this._contributions.values();
626+
}
627+
}
628+
629+
export const Extensions = {
630+
DragAndDropContribution: 'workbench.contributions.dragAndDrop'
631+
};
632+
633+
Registry.add(Extensions.DragAndDropContribution, new DragAndDropContributionRegistry());
634+
635+
//#endregion
636+
593637
//#region DND Utilities
594638

595639
/**

src/vs/workbench/browser/parts/editor/editorDropTarget.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import 'vs/css!./media/editordroptarget';
7-
import { LocalSelectionTransfer, DraggedEditorIdentifier, ResourcesDropHandler, DraggedEditorGroupIdentifier, containsDragType, CodeDataTransfers, DraggedTreeItemsIdentifier, extractTreeDropData } from 'vs/workbench/browser/dnd';
7+
import { Extensions as DragAndDropExtensions, LocalSelectionTransfer, DraggedEditorIdentifier, ResourcesDropHandler, DraggedEditorGroupIdentifier, containsDragType, CodeDataTransfers, DraggedTreeItemsIdentifier, extractTreeDropData, IDragAndDropContributionRegistry } from 'vs/workbench/browser/dnd';
88
import { addDisposableListener, EventType, EventHelper, isAncestor, DragAndDropObserver } from 'vs/base/browser/dom';
99
import { IEditorGroupsAccessor, IEditorGroupView, fillActiveEditorViewState } from 'vs/workbench/browser/parts/editor/editor';
1010
import { EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
@@ -22,6 +22,7 @@ import { assertIsDefined, assertAllDefined } from 'vs/base/common/types';
2222
import { ITreeViewsService } from 'vs/workbench/services/views/browser/treeViewsService';
2323
import { isTemporaryWorkspace, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
2424
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
25+
import { Registry } from 'vs/platform/registry/common/platform';
2526

2627
interface IDropOperation {
2728
splitDirection?: GroupDirection;
@@ -575,10 +576,14 @@ export class EditorDropTarget extends Themable {
575576
if (
576577
!this.editorTransfer.hasData(DraggedEditorIdentifier.prototype) &&
577578
!this.groupTransfer.hasData(DraggedEditorGroupIdentifier.prototype) &&
578-
event.dataTransfer && !containsDragType(event, DataTransfers.FILES, CodeDataTransfers.FILES, DataTransfers.RESOURCES, DataTransfers.TERMINALS, CodeDataTransfers.EDITORS) // see https://github.com/microsoft/vscode/issues/25789
579+
event.dataTransfer
579580
) {
580-
event.dataTransfer.dropEffect = 'none';
581-
return; // unsupported transfer
581+
const dndContributions = Registry.as<IDragAndDropContributionRegistry>(DragAndDropExtensions.DragAndDropContribution).getAll();
582+
const dndContributionKeys = Array.from(dndContributions).map(e => e.dataFormatKey);
583+
if (!containsDragType(event, DataTransfers.FILES, CodeDataTransfers.FILES, DataTransfers.RESOURCES, CodeDataTransfers.EDITORS, ...dndContributionKeys)) { // see https://github.com/microsoft/vscode/issues/25789
584+
event.dataTransfer.dropEffect = 'none';
585+
return; // unsupported transfer
586+
}
582587
}
583588

584589
// Signal DND start

src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,22 @@ import 'vs/css!./media/terminal';
99
import 'vs/css!./media/widgets';
1010
import 'vs/css!./media/xterm';
1111
import * as nls from 'vs/nls';
12+
import { URI } from 'vs/base/common/uri';
1213
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
1314
import { ContextKeyExpr, ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
1415
import { KeybindingWeight, KeybindingsRegistry, IKeybindings } from 'vs/platform/keybinding/common/keybindingsRegistry';
1516
import { Registry } from 'vs/platform/registry/common/platform';
1617
import { getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess';
1718
import { Extensions as ViewContainerExtensions, IViewContainersRegistry, ViewContainerLocation, IViewsRegistry } from 'vs/workbench/common/views';
19+
import { Extensions as DragAndDropExtensions, IDragAndDropContributionRegistry, IDraggedResourceEditorInput } from 'vs/workbench/browser/dnd';
1820
import { registerTerminalActions, terminalSendSequenceCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions';
1921
import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView';
2022
import { TERMINAL_VIEW_ID, TerminalCommandId, ITerminalProfileService } from 'vs/workbench/contrib/terminal/common/terminal';
2123
import { registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
2224
import { setupTerminalCommands } from 'vs/workbench/contrib/terminal/browser/terminalCommands';
2325
import { TerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService';
2426
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
25-
import { ITerminalEditorService, ITerminalGroupService, ITerminalInstanceService, ITerminalService, terminalEditorId } from 'vs/workbench/contrib/terminal/browser/terminal';
27+
import { ITerminalEditorService, ITerminalGroupService, ITerminalInstanceService, ITerminalService, TerminalDataTransfers, terminalEditorId } from 'vs/workbench/contrib/terminal/browser/terminal';
2628
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
2729
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
2830
import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess';
@@ -49,6 +51,7 @@ import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } fr
4951
import { RemoteTerminalBackendContribution } from 'vs/workbench/contrib/terminal/browser/remoteTerminalBackend';
5052
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
5153
import { TerminalMainContribution } from 'vs/workbench/contrib/terminal/browser/terminalMainContribution';
54+
import { Schemas } from 'vs/base/common/network';
5255

5356
// Register services
5457
registerSingleton(ITerminalService, TerminalService, true);
@@ -81,6 +84,7 @@ workbenchRegistry.registerWorkbenchContribution(RemoteTerminalBackendContributio
8184
registerTerminalPlatformConfiguration();
8285
registerTerminalConfiguration();
8386

87+
// Register editor/dnd contributions
8488
Registry.as<IEditorFactoryRegistry>(EditorExtensions.EditorFactory).registerEditorSerializer(TerminalEditorInput.ID, TerminalInputSerializer);
8589
Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane(
8690
EditorPaneDescriptor.create(
@@ -92,6 +96,27 @@ Registry.as<IEditorPaneRegistry>(EditorExtensions.EditorPane).registerEditorPane
9296
new SyncDescriptor(TerminalEditorInput)
9397
]
9498
);
99+
Registry.as<IDragAndDropContributionRegistry>(DragAndDropExtensions.DragAndDropContribution).register({
100+
dataFormatKey: TerminalDataTransfers.Terminals,
101+
getEditorInputs(data) {
102+
const editors: IDraggedResourceEditorInput[] = [];
103+
try {
104+
const terminalEditors: string[] = JSON.parse(data);
105+
for (const terminalEditor of terminalEditors) {
106+
editors.push({ resource: URI.parse(terminalEditor) });
107+
}
108+
} catch (error) {
109+
// Invalid transfer
110+
}
111+
return editors;
112+
},
113+
setData(resources, event) {
114+
const terminalResources = resources.filter(({ resource }) => resource.scheme === Schemas.vscodeTerminal);
115+
if (terminalResources.length) {
116+
event.dataTransfer?.setData(TerminalDataTransfers.Terminals, JSON.stringify(terminalResources.map(({ resource }) => resource.toString())));
117+
}
118+
}
119+
});
95120

96121
// Register views
97122
const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({

src/vs/workbench/contrib/terminal/browser/terminal.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,3 +918,7 @@ export const enum LinuxDistro {
918918
Fedora = 2,
919919
Ubuntu = 3,
920920
}
921+
922+
export const enum TerminalDataTransfers {
923+
Terminals = 'Terminals'
924+
}

src/vs/workbench/contrib/terminal/browser/terminalInstance.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import { CodeDataTransfers, containsDragType } from 'vs/workbench/browser/dnd';
5252
import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views';
5353
import { IDetectedLinks, TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager';
5454
import { TerminalLinkQuickpick } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkQuickpick';
55-
import { IRequestAddInstanceToGroupEvent, ITerminalExternalLinkProvider, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
55+
import { IRequestAddInstanceToGroupEvent, ITerminalExternalLinkProvider, ITerminalInstance, TerminalDataTransfers } from 'vs/workbench/contrib/terminal/browser/terminal';
5656
import { TerminalLaunchHelpAction } from 'vs/workbench/contrib/terminal/browser/terminalActions';
5757
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
5858
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
@@ -2282,7 +2282,7 @@ class TerminalInstanceDragAndDropController extends Disposable implements dom.ID
22822282
}
22832283

22842284
onDragEnter(e: DragEvent) {
2285-
if (!containsDragType(e, DataTransfers.FILES, DataTransfers.RESOURCES, DataTransfers.TERMINALS, CodeDataTransfers.FILES)) {
2285+
if (!containsDragType(e, DataTransfers.FILES, DataTransfers.RESOURCES, TerminalDataTransfers.Terminals, CodeDataTransfers.FILES)) {
22862286
return;
22872287
}
22882288

@@ -2292,7 +2292,7 @@ class TerminalInstanceDragAndDropController extends Disposable implements dom.ID
22922292
}
22932293

22942294
// Dragging terminals
2295-
if (containsDragType(e, DataTransfers.TERMINALS)) {
2295+
if (containsDragType(e, TerminalDataTransfers.Terminals)) {
22962296
const side = this._getDropSide(e);
22972297
this._dropOverlay.classList.toggle('drop-before', side === 'before');
22982298
this._dropOverlay.classList.toggle('drop-after', side === 'after');
@@ -2316,7 +2316,7 @@ class TerminalInstanceDragAndDropController extends Disposable implements dom.ID
23162316
}
23172317

23182318
// Dragging terminals
2319-
if (containsDragType(e, DataTransfers.TERMINALS)) {
2319+
if (containsDragType(e, TerminalDataTransfers.Terminals)) {
23202320
const side = this._getDropSide(e);
23212321
this._dropOverlay.classList.toggle('drop-before', side === 'before');
23222322
this._dropOverlay.classList.toggle('drop-after', side === 'after');

src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
99
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
1010
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
1111
import { IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
12-
import { ITerminalGroupService, ITerminalInstance, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
12+
import { ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalDataTransfers } from 'vs/workbench/contrib/terminal/browser/terminal';
1313
import { localize } from 'vs/nls';
1414
import * as DOM from 'vs/base/browser/dom';
1515
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -585,13 +585,13 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop<ITerminalInstance> {
585585
// Attach terminals type to event
586586
const terminals: ITerminalInstance[] = dndData.filter(e => 'instanceId' in (e as any));
587587
if (terminals.length > 0) {
588-
originalEvent.dataTransfer.setData(DataTransfers.TERMINALS, JSON.stringify(terminals.map(e => e.resource.toString())));
588+
originalEvent.dataTransfer.setData(TerminalDataTransfers.Terminals, JSON.stringify(terminals.map(e => e.resource.toString())));
589589
}
590590
}
591591

592592
onDragOver(data: IDragAndDropData, targetInstance: ITerminalInstance | undefined, targetIndex: number | undefined, originalEvent: DragEvent): boolean | IListDragOverReaction {
593593
if (data instanceof NativeDragAndDropData) {
594-
if (!containsDragType(originalEvent, DataTransfers.FILES, DataTransfers.RESOURCES, DataTransfers.TERMINALS, CodeDataTransfers.FILES)) {
594+
if (!containsDragType(originalEvent, DataTransfers.FILES, DataTransfers.RESOURCES, TerminalDataTransfers.Terminals, CodeDataTransfers.FILES)) {
595595
return false;
596596
}
597597
}
@@ -602,7 +602,7 @@ class TerminalTabsDragAndDrop implements IListDragAndDrop<ITerminalInstance> {
602602
this._autoFocusInstance = targetInstance;
603603
}
604604

605-
if (!targetInstance && !containsDragType(originalEvent, DataTransfers.TERMINALS)) {
605+
if (!targetInstance && !containsDragType(originalEvent, TerminalDataTransfers.Terminals)) {
606606
return data instanceof ElementsDragAndDropData;
607607
}
608608

src/vs/workbench/contrib/terminal/browser/terminalUri.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { DataTransfers } from 'vs/base/browser/dnd';
76
import { Schemas } from 'vs/base/common/network';
87
import { URI } from 'vs/base/common/uri';
9-
import { ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal';
8+
import { ITerminalInstance, TerminalDataTransfers } from 'vs/workbench/contrib/terminal/browser/terminal';
109

1110
export function parseTerminalUri(resource: URI): ITerminalIdentifier {
1211
const [, workspaceId, instanceId] = resource.path.split('/');
@@ -34,7 +33,7 @@ export interface IPartialDragEvent {
3433
}
3534

3635
export function getTerminalResourcesFromDragEvent(event: IPartialDragEvent): URI[] | undefined {
37-
const resources = event.dataTransfer?.getData(DataTransfers.TERMINALS);
36+
const resources = event.dataTransfer?.getData(TerminalDataTransfers.Terminals);
3837
if (resources) {
3938
const json = JSON.parse(resources);
4039
const result = [];

src/vs/workbench/contrib/terminal/browser/terminalView.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { IThemeService, IColorTheme, registerThemingParticipant, ICssStyleCollec
1414
import { switchTerminalActionViewItemSeparator, switchTerminalShowTabsTitle } from 'vs/workbench/contrib/terminal/browser/terminalActions';
1515
import { TERMINAL_BACKGROUND_COLOR, TERMINAL_BORDER_COLOR, TERMINAL_DRAG_AND_DROP_BACKGROUND, TERMINAL_TAB_ACTIVE_BORDER } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
1616
import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification';
17-
import { ICreateTerminalOptions, ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal';
17+
import { ICreateTerminalOptions, ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalConnectionState, TerminalDataTransfers } from 'vs/workbench/contrib/terminal/browser/terminal';
1818
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane';
1919
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
2020
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -42,7 +42,6 @@ import { ColorScheme } from 'vs/platform/theme/common/theme';
4242
import { getColorClass, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
4343
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
4444
import { withNullAsUndefined } from 'vs/base/common/types';
45-
import { DataTransfers } from 'vs/base/browser/dnd';
4645
import { getTerminalActionBarArgs } from 'vs/workbench/contrib/terminal/browser/terminalMenus';
4746
import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey';
4847
import { getShellIntegrationTooltip } from 'vs/workbench/contrib/terminal/browser/terminalTooltip';
@@ -449,7 +448,7 @@ class SingleTerminalTabActionViewItem extends MenuEntryActionViewItem {
449448
this._elementDisposables.push(dom.addDisposableListener(this.element, dom.EventType.DRAG_START, e => {
450449
const instance = this._terminalGroupService.activeInstance;
451450
if (e.dataTransfer && instance) {
452-
e.dataTransfer.setData(DataTransfers.TERMINALS, JSON.stringify([instance.resource.toString()]));
451+
e.dataTransfer.setData(TerminalDataTransfers.Terminals, JSON.stringify([instance.resource.toString()]));
453452
}
454453
}));
455454
}

0 commit comments

Comments
 (0)