-
Notifications
You must be signed in to change notification settings - Fork 8.7k
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
Conversation
// 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); | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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)); | ||
} |
There was a problem hiding this comment.
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.
src/host/consoleInformation.cpp
Outdated
const auto clipboardText = _pendingClipboardText; | ||
_pendingClipboardText.reset(); | ||
return clipboardText; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this 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. :)
/azp run |
Azure Pipelines successfully started running 1 pipeline(s). |
## 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
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
## 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
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