diff --git a/extensions/markdown-language-features/src/extension.ts b/extensions/markdown-language-features/src/extension.ts index 022ab92f11e..b54bd8590a8 100644 --- a/extensions/markdown-language-features/src/extension.ts +++ b/extensions/markdown-language-features/src/extension.ts @@ -50,13 +50,13 @@ export function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.workspace.onWillDropOnTextEditor(e => { e.waitUntil((async () => { - const resourceUrls = await e.dataTransfer.get('resourceurls')?.asString(); - if (!resourceUrls) { + const urlList = await e.dataTransfer.get('text/uri-list')?.asString(); + if (!urlList) { return; } const uris: vscode.Uri[] = []; - for (const resource of JSON.parse(resourceUrls)) { + for (const resource of urlList.split('\n')) { try { uris.push(vscode.Uri.parse(resource)); } catch { diff --git a/src/vs/editor/browser/editorBrowser.ts b/src/vs/editor/browser/editorBrowser.ts index 8ed06d0f3ac..03bbb10f077 100644 --- a/src/vs/editor/browser/editorBrowser.ts +++ b/src/vs/editor/browser/editorBrowser.ts @@ -614,7 +614,7 @@ export interface ICodeEditor extends editorCommon.IEditor { * @internal * @event */ - readonly onDropIntoEditor: Event<{ readonly position: IPosition; readonly dataTransfer: DataTransfer }>; + readonly onDropIntoEditor: Event<{ readonly position: IPosition; readonly event: DragEvent }>; /** * An event emitted on a "contextmenu". * @event diff --git a/src/vs/editor/browser/widget/codeEditorWidget.ts b/src/vs/editor/browser/widget/codeEditorWidget.ts index 003981141c6..f3fa880bf88 100644 --- a/src/vs/editor/browser/widget/codeEditorWidget.ts +++ b/src/vs/editor/browser/widget/codeEditorWidget.ts @@ -190,7 +190,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE private readonly _onMouseDropCanceled: Emitter = this._register(new Emitter()); public readonly onMouseDropCanceled: Event = this._onMouseDropCanceled.event; - private readonly _onDropIntoEditor = this._register(new Emitter<{ position: IPosition; dataTransfer: DataTransfer }>()); + private readonly _onDropIntoEditor = this._register(new Emitter<{ readonly position: IPosition; readonly event: DragEvent }>()); public readonly onDropIntoEditor = this._onDropIntoEditor.event; private readonly _onContextMenu: Emitter = this._register(new Emitter()); @@ -379,7 +379,7 @@ export class CodeEditorWidget extends Disposable implements editorBrowser.ICodeE const target = this.getTargetAtClientPoint(e.clientX, e.clientY); if (target?.position) { - this._onDropIntoEditor.fire({ position: target.position, dataTransfer: e.dataTransfer }); + this._onDropIntoEditor.fire({ position: target.position, event: e }); } }, onDragLeave: () => { diff --git a/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts b/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts index f24b5ecb04d..afb6fb751a4 100644 --- a/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadDocumentsAndEditors.ts @@ -33,6 +33,7 @@ import { IPathService } from 'vs/workbench/services/path/common/pathService'; import { diffSets, diffMaps } from 'vs/base/common/collections'; import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; import { ViewContainerLocation } from 'vs/workbench/common/views'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; class TextEditorSnapshot { @@ -297,14 +298,15 @@ export class MainThreadDocumentsAndEditors { @IWorkingCopyFileService workingCopyFileService: IWorkingCopyFileService, @IUriIdentityService uriIdentityService: IUriIdentityService, @IClipboardService private readonly _clipboardService: IClipboardService, - @IPathService pathService: IPathService + @IPathService pathService: IPathService, + @IInstantiationService instantiationService: IInstantiationService ) { this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentsAndEditors); this._mainThreadDocuments = this._toDispose.add(new MainThreadDocuments(extHostContext, this._modelService, this._textFileService, fileService, textModelResolverService, environmentService, uriIdentityService, workingCopyFileService, pathService)); extHostContext.set(MainContext.MainThreadDocuments, this._mainThreadDocuments); - this._mainThreadEditors = this._toDispose.add(new MainThreadTextEditors(this, extHostContext, codeEditorService, bulkEditService, this._editorService, this._editorGroupService)); + this._mainThreadEditors = this._toDispose.add(new MainThreadTextEditors(this, extHostContext, codeEditorService, bulkEditService, this._editorService, this._editorGroupService, instantiationService)); extHostContext.set(MainContext.MainThreadTextEditors, this._mainThreadEditors); // It is expected that the ctor of the state computer calls our `_onDelta`. diff --git a/src/vs/workbench/api/browser/mainThreadEditors.ts b/src/vs/workbench/api/browser/mainThreadEditors.ts index 3d41b31b997..4869b6f8bb8 100644 --- a/src/vs/workbench/api/browser/mainThreadEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadEditors.ts @@ -15,7 +15,7 @@ import { IDecorationOptions, IDecorationRenderOptions } from 'vs/editor/common/e import { ISingleEditOperation } from 'vs/editor/common/core/editOperation'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { ITextEditorOptions, IResourceEditorInput, EditorActivation, EditorResolution } from 'vs/platform/editor/common/editor'; -import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; +import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { MainThreadTextEditor } from 'vs/workbench/api/browser/mainThreadEditor'; import { ExtHostContext, ExtHostEditorsShape, IApplyEditsOptions, ITextDocumentShowOptions, ITextEditorConfigurationUpdate, ITextEditorPositionData, IUndoStopOptions, MainThreadTextEditorsShape, TextEditorRevealType, IWorkspaceEditDto, WorkspaceEditType } from 'vs/workbench/api/common/extHost.protocol'; import { editorGroupToColumn, columnToEditorGroup, EditorGroupColumn } from 'vs/workbench/services/editor/common/editorGroupColumn'; @@ -34,7 +34,9 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; import { DataTransferConverter } from 'vs/workbench/api/common/shared/dataTransfer'; import { IPosition } from 'vs/editor/common/core/position'; import { IDataTransfer, IDataTransferItem } from 'vs/workbench/common/dnd'; -import { DataTransfers } from 'vs/base/browser/dnd'; +import { extractEditorsDropData } from 'vs/workbench/browser/dnd'; +import { Mimes } from 'vs/base/common/mime'; +import { distinct } from 'vs/base/common/arrays'; export function reviveWorkspaceEditDto2(data: IWorkspaceEditDto | undefined): ResourceEdit[] { if (!data?.edits) { @@ -79,6 +81,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { @IBulkEditService private readonly _bulkEditService: IBulkEditService, @IEditorService private readonly _editorService: IEditorService, @IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService, + @IInstantiationService private readonly _instantiationService: IInstantiationService, ) { this._instanceId = String(++MainThreadTextEditors.INSTANCE_COUNT); this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostEditors); @@ -92,7 +95,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { const registerDropListenerOnEditor = (editor: ICodeEditor) => { this._dropIntoEditorListeners.get(editor)?.dispose(); - this._dropIntoEditorListeners.set(editor, editor.onDropIntoEditor(e => this.onDropIntoEditor(editor, e.position, e.dataTransfer))); + this._dropIntoEditorListeners.set(editor, editor.onDropIntoEditor(e => this.onDropIntoEditor(editor, e.position, e.event))); }; this._toDispose.add(_codeEditorService.onCodeEditorAdd(registerDropListenerOnEditor)); @@ -158,15 +161,17 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { return result; } - private async onDropIntoEditor(editor: ICodeEditor, position: IPosition, dataTransfer: DataTransfer) { + private async onDropIntoEditor(editor: ICodeEditor, position: IPosition, dragEvent: DragEvent) { + if (!dragEvent.dataTransfer) { + return; + } const id = this._editorLocator.getIdOfCodeEditor(editor); if (typeof id !== 'string') { return; } const textEditorDataTransfer: IDataTransfer = new Map(); - const fileUris: string[] = []; - for (const item of dataTransfer.items) { + for (const item of dragEvent.dataTransfer.items) { if (item.kind === 'string') { const type = item.type; const asStringValue = new Promise(resolve => item.getAsString(resolve)); @@ -174,20 +179,21 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape { asString: () => asStringValue, value: undefined }); - } else if (item.kind === 'file') { - const file = item.getAsFile(); - if (file?.path) { - fileUris.push(file.path); - } } } - if (fileUris.length && !textEditorDataTransfer.has(DataTransfers.RESOURCES.toLowerCase())) { - const str = JSON.stringify(fileUris); - textEditorDataTransfer.set(DataTransfers.RESOURCES.toLowerCase(), { - asString: () => Promise.resolve(str), - value: undefined - }); + if (!textEditorDataTransfer.has(Mimes.uriList.toLowerCase())) { + const editorData = (await this._instantiationService.invokeFunction(extractEditorsDropData, dragEvent)) + .filter(input => input.resource) + .map(input => input.resource!.toString()); + + if (editorData.length) { + const str = distinct(editorData).join('\n'); + textEditorDataTransfer.set(Mimes.uriList.toLowerCase(), { + asString: () => Promise.resolve(str), + value: undefined + }); + } } if (textEditorDataTransfer.size > 0) { diff --git a/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts b/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts index cbe44917b29..adfaa71f27b 100644 --- a/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts +++ b/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts @@ -34,6 +34,7 @@ import { LanguageService } from 'vs/editor/common/services/languageService'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { LanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce'; import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeaturesService'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; suite('MainThreadDocumentsAndEditors', () => { @@ -120,7 +121,8 @@ suite('MainThreadDocumentsAndEditors', () => { return Promise.resolve('clipboard_contents'); } }, - new TestPathService() + new TestPathService(), + new TestInstantiationService(), ); });