Microsoft/vscode

Only on macOS , some drag-and-drop interactions fail within iframe in extension's webview

Open

#193,558 opened on 2023年9月20日

GitHub で見る
 (9 comments) (0 reactions) (1 assignee)TypeScript (10,221 forks)batch import
bughelp wantedwebview

Repository metrics

Stars
 (74,848 stars)
PR merge metrics
 (平均マージ 11h 43m) (30d で 1,000 merged PRs)

説明

Does this issue occur when all extensions are disabled?: Yes/No

  • VS Code Version: 1.82
  • OS Version: macOS Ventura 13.5.2

Steps to Reproduce:

  1. Create a new vscode extension (or use one that you already have)
  2. Create a WebView that contains an HTML document, where an iframe loads an external HTML resource via src. This HTML resource includes a div and a draggable button. Visiting this HTML independently allows dragging the button into the div. (see example code below)
  3. Run the extension and webview to load the demo
  4. Try to drag a button into the div.

More Information

I am building a low-code plugin for VS Code that allows users to drag and drop components to build the basic layout of a web page. Currently, this functionality works perfectly fine in the Chrome browser.

However, when I tried to use a VS Code extension to make it work within the VS Code editor, I encountered some issues. Essentially, my extension creates a WebView with an iframe that loads an external website I created, which contains multiple drag-and-drop events.

I have seen similar issues reported in the issue tracker and the behavior seems to be exactly the same. Unfortunately, the problem has not been resolved and the issue has been closed. Therefore, I had to create a new issue seeking help from the development team.

There are two interesting observations so far:

  1. The mentioned issue only occurs on macOS(both Apple silicon and intel). On Windows, everything works fine and I can trigger drag and drop events within the iframe of the WebView without any problems. (I haven't tested it on Linux since I don't have a Linux environment.)

  2. When I directly include the entire external HTML code in the iframe of the WebView using the "srcdoc" approach, the drag and drop events work correctly as well. Based on my analysis, I suspect that this issue may be related to resource restrictions within VS Code WebView and file access. However, it's still unclear why it performs well on the Windows platform.

I have provided a simplified version of the VS Code plugin demo. In the "src/view" folder, there are two HTML files that use different iframe referencing modes: "srcdoc" and "src". I hope this can help the development team quickly identify the problem.

As a quick reference, here's how I'm creating the webview:

const vscode = require('vscode');

/**
 * @param {vscode.ExtensionContext} context
 */
function activate(context) {
	console.log('Congratulations, your extension "visualEditor" is now active!');
	let disposable = vscode.commands.registerCommand('visualeditor.openVisualEditor', function () {
		const panel = vscode.window.createWebviewPanel(
			'visualEditor',
			'Visual Editor',
			vscode.ViewColumn.One,
			{	enableScripts: true	}
		  );
	
		  
		  panel.webview.html = `<!DOCTYPE html>
		  <html lang="en">
		  <head>
			  <meta charset="UTF-8">
			  <meta name="viewport" content="width=device-width, initial-scale=1.0">
			  <title>Visual Editor</title>
		  </head>
		  <body style="padding: 0 0px;">
                           # The 'src' parameter below can be replaced with any HTML address that contains drag and drop events (you can use the HTML from the demo version I wrote, run it on a separate server, and configure the server address in the iframe).
			  <iframe src="https://grapesjs.com/demo.html" style="position: fixed; width: 100%; height: 100%;">
			</iframe>
		  </body>
		  </html>`
	});

	context.subscriptions.push(disposable);
}

function deactivate() {}

module.exports = {
	activate,
	deactivate
}

And,here's demo html with drag envent

<!DOCTYPE html>
<html>

<body>
  <div id="testDemo" style="width:800px;height:200px;background-color:pink">
    aaaabbbbs123
  </div>
  <button draggable="true" id="btn">drag me</button>

  <script>
    window.onload = function () {

      let dragged = null;

      const source = document.getElementById("btn");
      source.addEventListener("dragstart", (event) => {
        dragged = event.target;
      });


      const target = document.getElementById("testDemo");
      target.addEventListener("dragover", (event) => {
        event.preventDefault();
      });

      target.addEventListener("drop", (event) => {
        event.preventDefault();
        event.target.appendChild(dragged);

      });
    }
  </script>
</body>

</html>

Finally, I appreciate your response, and if necessary, I can provide more information or a demo to assist in resolving this issue.

Many Thanks.

コントリビューターガイド