diff --git a/src/vs/workbench/contrib/webview/browser/pre/index.html b/src/vs/workbench/contrib/webview/browser/pre/index.html
index 7629db38a295c..0c6829c08f8b0 100644
--- a/src/vs/workbench/contrib/webview/browser/pre/index.html
+++ b/src/vs/workbench/contrib/webview/browser/pre/index.html
@@ -5,7 +5,9 @@
+
+ content="default-src 'none'; script-src 'sha256-EJBlYt9sOvo6RhZZJG+duTqIZCB8pctk1a62h/ZIElc=' 'self'; frame-src 'self'; style-src 'unsafe-inline';">
+
void} callback
*/
@@ -881,7 +894,9 @@
window.addEventListener('keydown', handleInnerKeydown);
window.addEventListener('keyup', handleInnerKeyup);
window.addEventListener('dragenter', handleInnerDragStartEvent);
- window.addEventListener('dragover', handleInnerDragStartEvent);
+ window.addEventListener('dragover', handleInnerDragEvent);
+ window.addEventListener('drag', handleInnerDragEvent);
+
onDomReady(() => {
if (!document.body) {
@@ -1163,7 +1178,8 @@
});
contentWindow.addEventListener('dragenter', handleInnerDragStartEvent);
- contentWindow.addEventListener('dragover', handleInnerDragStartEvent);
+ contentWindow.addEventListener('dragover', handleInnerDragEvent);
+ contentWindow.addEventListener('drag', handleInnerDragEvent);
unloadMonitor.onIframeLoaded(newFrame);
}
diff --git a/src/vs/workbench/contrib/webview/browser/webviewElement.ts b/src/vs/workbench/contrib/webview/browser/webviewElement.ts
index 3d5d21f080f7f..5d6e403159f46 100644
--- a/src/vs/workbench/contrib/webview/browser/webviewElement.ts
+++ b/src/vs/workbench/contrib/webview/browser/webviewElement.ts
@@ -34,7 +34,7 @@ import { loadLocalResource, WebviewResourceResponse } from 'vs/workbench/contrib
import { WebviewThemeDataProvider } from 'vs/workbench/contrib/webview/browser/themeing';
import { areWebviewContentOptionsEqual, IWebview, WebviewContentOptions, WebviewExtensionDescription, WebviewInitInfo, WebviewMessageReceivedEvent, WebviewOptions } from 'vs/workbench/contrib/webview/browser/webview';
import { WebviewFindDelegate, WebviewFindWidget } from 'vs/workbench/contrib/webview/browser/webviewFindWidget';
-import { FromWebviewMessage, KeyEvent, ToWebviewMessage } from 'vs/workbench/contrib/webview/browser/webviewMessages';
+import { FromWebviewMessage, KeyEvent, ToWebviewMessage, WebViewDragEvent } from 'vs/workbench/contrib/webview/browser/webviewMessages';
import { decodeAuthority, webviewGenericCspSource, webviewRootResourceAuthority } from 'vs/workbench/contrib/webview/common/webview';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { CodeWindow } from 'vs/base/browser/window';
@@ -310,6 +310,10 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
this._startBlockingIframeDragEvents();
}));
+ this._register(this.on('drag', (event) => {
+ this.handleDragEvent('drag', event);
+ }));
+
if (initInfo.options.enableFindWidget) {
this._webviewFindWidget = this._register(instantiationService.createInstance(WebviewFindWidget, this));
}
@@ -697,6 +701,17 @@ export class WebviewElement extends Disposable implements IWebview, WebviewFindD
this.window?.dispatchEvent(emulatedKeyboardEvent);
}
+ private handleDragEvent(type: 'drag', event: WebViewDragEvent) {
+ // Create a fake DragEvent from the data provided
+ const emulatedDragEvent = new DragEvent(type, event);
+ // Force override the target
+ Object.defineProperty(emulatedDragEvent, 'target', {
+ get: () => this.element,
+ });
+ // And re-dispatch
+ this.window?.dispatchEvent(emulatedDragEvent);
+ }
+
windowDidDragStart(): void {
// Webview break drag and dropping around the main window (no events are generated when you are over them)
// Work around this by disabling pointer events during the drag.
diff --git a/src/vs/workbench/contrib/webview/browser/webviewMessages.d.ts b/src/vs/workbench/contrib/webview/browser/webviewMessages.d.ts
index eae9c80fa6872..dde553ec05724 100644
--- a/src/vs/workbench/contrib/webview/browser/webviewMessages.d.ts
+++ b/src/vs/workbench/contrib/webview/browser/webviewMessages.d.ts
@@ -17,6 +17,10 @@ type KeyEvent = {
repeat: boolean;
}
+type WebViewDragEvent = {
+ shiftKey: boolean;
+}
+
export type FromWebviewMessage = {
'onmessage': { message: any; transfer?: ArrayBuffer[] };
'did-click-link': { uri: string };
@@ -36,6 +40,7 @@ export type FromWebviewMessage = {
'did-keyup': KeyEvent;
'did-context-menu': { clientX: number; clientY: number; context: { [key: string]: unknown } };
'drag-start': void;
+ 'drag': WebViewDragEvent
};
interface UpdateContentEvent {
diff --git a/src/vs/workbench/contrib/webview/browser/webviewWindowDragMonitor.ts b/src/vs/workbench/contrib/webview/browser/webviewWindowDragMonitor.ts
index e4dc5eaf0e904..d009ae186da59 100644
--- a/src/vs/workbench/contrib/webview/browser/webviewWindowDragMonitor.ts
+++ b/src/vs/workbench/contrib/webview/browser/webviewWindowDragMonitor.ts
@@ -18,19 +18,41 @@ export class WebviewWindowDragMonitor extends Disposable {
constructor(targetWindow: CodeWindow, getWebview: () => IWebview | undefined) {
super();
- this._register(DOM.addDisposableListener(targetWindow, DOM.EventType.DRAG_START, () => {
+ const onDragStart = () => {
getWebview()?.windowDidDragStart();
- }));
+ };
const onDragEnd = () => {
getWebview()?.windowDidDragEnd();
};
+ this._register(DOM.addDisposableListener(targetWindow, DOM.EventType.DRAG_START, () => {
+ onDragStart();
+ }));
+
this._register(DOM.addDisposableListener(targetWindow, DOM.EventType.DRAG_END, onDragEnd));
+
this._register(DOM.addDisposableListener(targetWindow, DOM.EventType.MOUSE_MOVE, currentEvent => {
if (currentEvent.buttons === 0) {
onDragEnd();
}
}));
+
+ this._register(DOM.addDisposableListener(targetWindow, DOM.EventType.DRAG, (event) => {
+ if (event.shiftKey) {
+ onDragEnd();
+ } else {
+ onDragStart();
+ }
+ }));
+
+ this._register(DOM.addDisposableListener(targetWindow, DOM.EventType.DRAG_OVER, (event) => {
+ if (event.shiftKey) {
+ onDragEnd();
+ } else {
+ onDragStart();
+ }
+ }));
+
}
}