Skip to content

Webviews: Ctrl+C / context-menu Copy of selected text copies nothing when the webview's last focused element is editable (regression in 1.143.0) #344028

Closed as duplicate

Description

Type: Bug

Describe the bug

Since VS Code 1.143.0, copying selected text from webview content with Ctrl+C (or with Copy in the right-click context menu) no longer puts the text into the clipboard whenever the webview's "last focused element" is an editable element (an <input>, <textarea> or contenteditable). The selection highlight stays visible, but the clipboard is left unchanged — or is even cleared when nothing is selected. Re-focusing the editable element first (clicking into it) makes copy work again.

Steps to reproduce

  1. Use an extension whose webview contains both an editable element (e.g. a contenteditable composer or a text input) and selectable plain text (e.g. a paragraph of a chat transcript).
  2. Focus the editable element once (click into it / type something).
  3. Select any text in the non-editable part of the webview with the mouse.
  4. Press Ctrl+C (or right-click → Copy).
  5. Paste somewhere: the clipboard does not contain the selected text. With nothing selected, the previous clipboard content is cleared.

Also reproduced with a real-world chat-style extension (Qwen Code Companion, issue QwenLM/qwen-code#15402) on VS Code 1.143.0 / Linux x64; the same extension version copies fine on 1.142.x.

Root cause (from reading the shipped code)

In vs/workbench/contrib/webview/browser/pre/index.html, the execCommand host-message handler (the path used for Ctrl+C / context-menu Copy in webviews) gained a focus-restore step:

hostMessaging.onMessage('execCommand', (_event, data) => {
    ...
    const lastFocused = lastFocusedElements.get(contentDocument);
    if ((contentDocument.activeElement === contentDocument.body || contentDocument.activeElement === contentDocument.documentElement)
            && lastFocused?.isConnected && lastFocused.ownerDocument === contentDocument) {
        lastFocused.focus({ preventScroll: true });   // ← new in 1.143.0
    }
    contentDocument.execCommand(data);
});

When the user selects text in the webview's non-editable content, activeElement is <body>, so the handler refocuses the recorded "last focused element" right before running the copy. Focusing an editable element collapses the document selection, so execCommand('copy') then runs against an empty selection. Focusing a non-editable element would not clear the selection — which is why stock webviews without editables (e.g. the Markdown preview) still copy fine.

I confirmed this with instrumentation inside the webview: the copy event and document.execCommand('copy') both fire, but the selection is already empty at that point, immediately after a focusin on the editable delivered through the host messaging channel.

Expected behavior

Ctrl+C / context-menu Copy should copy the current webview selection regardless of which element was focused before. The focus restore added in 1.143.0 should not destroy a live selection — e.g. skip the refocus when the document has a non-collapsed selection, or save and restore the selection around the refocus.

VS Code version

Version: 1.143.0 (snap, revision 272)
OS: Linux x64

The previous revision (271, 1.142.x) does not have the refocus step and copies correctly.

Defensive workaround observed to work (used by the affected extension): on capture-phase pointerdown over non-interactive webview areas, focus the webview's non-editable root element — the active element is then no longer <body>, the guest script skips the refocus, and the copy runs against the live selection.

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions