Skip to content

Add support for OSC 52 clipboard copy in conhost #18949

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 10, 2025

Conversation

j4james
Copy link
Collaborator

@j4james j4james commented May 26, 2025

Summary of the Pull Request

This adds support for copying to the clipboard in conhost using the OSC
52 escape sequence, extending the original implementation which was for
Windows Terminal only.

References and Relevant Issues

The Windows Terminal implementation was added in PR #5823.

Detailed Description of the Pull Request / Additional comments

Because the clipboard can't be accessed from a background thread, this
works by saving the content in a global variable, and then posting a
custom message to the main GUI thread, which takes care of the actual
copy operation.

Validation Steps Performed

I've manually confirmed that tmux copy mode is now able to copy to the
system clipboard.

PR Checklist

Comment on lines +188 to +197
// The clipboard can only be updated from the main GUI thread, so we
// need to post a message to trigger the actual copy operation. But if
// the pending clipboard content is already set, a message would have
// already been posted, so there's no need to post another one.
const auto clipboardMessageSent = _pendingClipboardText.has_value();
_pendingClipboardText = text;
if (!clipboardMessageSent)
{
PostMessageW(window->GetWindowHandle(), CM_UPDATE_CLIPBOARD, 0, 0);
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if I've just misunderstood how you're supposed to use the windows clipboard, but I couldn't get it working from a background thread, and this technique worked for me. I don't know if maybe there's a better way to do this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, reading doesn't require a HWND but writing does, to my knowledge.

Comment on lines +27 to +41
void Clipboard::CopyText(const std::wstring& text)
{
const auto clipboard = _openClipboard(ServiceLocator::LocateConsoleWindow()->GetWindowHandle());
if (!clipboard)
{
LOG_LAST_ERROR();
return;
}

EmptyClipboard();
// As per: https://learn.microsoft.com/en-us/windows/win32/dataxchg/standard-clipboard-formats
// CF_UNICODETEXT: [...] A null character signals the end of the data.
// --> We add +1 to the length. This works because .c_str() is null-terminated.
_copyToClipboard(CF_UNICODETEXT, text.c_str(), (text.size() + 1) * sizeof(wchar_t));
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The content of this method is copied directly from StoreSelectionToClipboard, but there's really not much to it, so I didn't think there was any point in trying to share the code somehow.

Comment on lines 206 to 208
const auto clipboardText = _pendingClipboardText;
_pendingClipboardText.reset();
return clipboardText;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can avoid a copy here by doing this:

return std::exchange(_pendingClipboardText, {});

I've tested OSC 52 with Windows Terminal with up to 100MiB and it was relatively snappy. So I think avoiding a copy may be useful to reduce the peak memory usage.

...now that I mention this, I realize that immediately copying the clipboard contents into an HGLOBAL would have another benefit... Well, that's a minor issue though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the exchange suggestion. I was hoping there was way to avoid that copy. That's definitely made a difference.

Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concise and easy to review.

I'm going to attempt to backport this to Ge+ Windows as well. Just to keep the wheels turning. :)

@DHowett
Copy link
Member

DHowett commented Jun 10, 2025

/azp run

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@DHowett DHowett enabled auto-merge (squash) June 10, 2025 19:34
@DHowett DHowett merged commit 4abc041 into microsoft:main Jun 10, 2025
12 of 14 checks passed
carlos-zamora pushed a commit that referenced this pull request Jun 19, 2025
## Summary of the Pull Request
Some applications that make use of the `OSC 52` clipboard sequence will
only do so if they can be certain that the terminal actually has that
functionality. Indicating our support for `OSC 52` in the `DA1` report
will give them an easy way to detect that.

## References and Relevant Issues
`OSC 52` support was added to Windows Terminal in issue #5823, and to
ConHost in issue #18949.

## Detailed Description of the Pull Request / Additional comments
Support for writing to the clipboard is indicated in the primary device
attributes report by the extension parameter `52`. This is obviously not
a standard DEC extension, but it's one that's been agreed upon by a
number of modern terminals. The extension is only reported when writing
to the clipboard is actually permitted (Windows Terminal has an option
to disable that).

## Validation Steps Performed
I've updated the Device Attributes unit test to check that we're
reporting extension `52` when clipboard access is enabled, and not
reporting it when disabled.

## PR Checklist
- [x] Closes #19017
- [x] Tests added/passed
DHowett pushed a commit that referenced this pull request Jun 24, 2025
Some applications that make use of the `OSC 52` clipboard sequence will
only do so if they can be certain that the terminal actually has that
functionality. Indicating our support for `OSC 52` in the `DA1` report
will give them an easy way to detect that.

`OSC 52` support was added to Windows Terminal in issue #5823, and to
ConHost in issue #18949.

Support for writing to the clipboard is indicated in the primary device
attributes report by the extension parameter `52`. This is obviously not
a standard DEC extension, but it's one that's been agreed upon by a
number of modern terminals. The extension is only reported when writing
to the clipboard is actually permitted (Windows Terminal has an option
to disable that).

I've updated the Device Attributes unit test to check that we're
reporting extension `52` when clipboard access is enabled, and not
reporting it when disabled.

- [x] Closes #19017
- [x] Tests added/passed

(cherry picked from commit 00ee884)
Service-Card-Id: PVTI_lADOAF3p4s4AmhmQzgbpe4k
Service-Version: 1.22
DHowett pushed a commit that referenced this pull request Jun 24, 2025
## Summary of the Pull Request
Some applications that make use of the `OSC 52` clipboard sequence will
only do so if they can be certain that the terminal actually has that
functionality. Indicating our support for `OSC 52` in the `DA1` report
will give them an easy way to detect that.

## References and Relevant Issues
`OSC 52` support was added to Windows Terminal in issue #5823, and to
ConHost in issue #18949.

## Detailed Description of the Pull Request / Additional comments
Support for writing to the clipboard is indicated in the primary device
attributes report by the extension parameter `52`. This is obviously not
a standard DEC extension, but it's one that's been agreed upon by a
number of modern terminals. The extension is only reported when writing
to the clipboard is actually permitted (Windows Terminal has an option
to disable that).

## Validation Steps Performed
I've updated the Device Attributes unit test to check that we're
reporting extension `52` when clipboard access is enabled, and not
reporting it when disabled.

## PR Checklist
- [x] Closes #19017
- [x] Tests added/passed

(cherry picked from commit 00ee884)
Service-Card-Id: PVTI_lADOAF3p4s4Axadtzgbpe4g
Service-Version: 1.23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: To Cherry Pick
Development

Successfully merging this pull request may close these issues.

Add support for OSC 52 clipboard copies in conhost
3 participants