-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Add support for OSC 52 (copy-to-clipboard) #5823
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
Changes from 4 commits
e4fe3fc
946ac27
0fa22cb
dcac598
1e462be
559f7fc
644ba34
e8eb5ef
91a3843
2c9c297
3b16808
83d6700
5d8a07b
56719e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,8 @@ | |
| #include "ascii.hpp" | ||
| using namespace Microsoft::Console; | ||
| using namespace Microsoft::Console::VirtualTerminal; | ||
| using namespace winrt::Windows::Security::Cryptography; | ||
| using namespace winrt::Windows::Storage::Streams; | ||
|
|
||
| // takes ownership of pDispatch | ||
| OutputStateMachineEngine::OutputStateMachineEngine(std::unique_ptr<ITermDispatch> pDispatch) : | ||
|
|
@@ -726,6 +728,8 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/, | |
| { | ||
| bool success = false; | ||
| std::wstring title; | ||
| std::wstring setClipboardContent; | ||
| bool queryClipboard = false; | ||
| size_t tableIndex = 0; | ||
| DWORD color = 0; | ||
|
|
||
|
|
@@ -744,6 +748,9 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/, | |
| case OscActionCodes::SetCursorColor: | ||
| success = _GetOscSetColor(string, color); | ||
| break; | ||
| case OscActionCodes::SetClipboard: | ||
| success = _GetOscSetClipboard(string, setClipboardContent, queryClipboard); | ||
| break; | ||
| case OscActionCodes::ResetCursorColor: | ||
| // the console uses 0xffffffff as an "invalid color" value | ||
| color = 0xffffffff; | ||
|
|
@@ -780,6 +787,13 @@ bool OutputStateMachineEngine::ActionOscDispatch(const wchar_t /*wch*/, | |
| success = _dispatch->SetCursorColor(color); | ||
| TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCSCC); | ||
| break; | ||
| case OscActionCodes::SetClipboard: | ||
| if (!queryClipboard) | ||
| { | ||
| success = _dispatch->SetClipboard(setClipboardContent); | ||
| } | ||
| TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCSCC); | ||
|
||
| break; | ||
| case OscActionCodes::ResetCursorColor: | ||
| success = _dispatch->SetCursorColor(color); | ||
| TermTelemetry::Instance().Log(TermTelemetry::Codes::OSCRCC); | ||
|
|
@@ -1731,6 +1745,47 @@ bool OutputStateMachineEngine::_GetRepeatCount(std::basic_string_view<size_t> pa | |
| return success; | ||
| } | ||
|
|
||
| // Routine Description: | ||
| // - Parse OscSetClipboard parameters with the format `Pc;Pd`. Currently the first parameter `Pc` is | ||
| // ignored. The second parameter `Pd` should be a valid base64 string or character `?`. | ||
| // Arguments: | ||
| // - string - Osc String input. | ||
| // - content - Content to set to clipboard. | ||
| // - queryClipboard - Whether to get clipboard content and return it to terminal with base64 encoded. | ||
| // Return Value: | ||
| // - True if there was a valid base64 string or the passed parameter was `?`. | ||
| bool OutputStateMachineEngine::_GetOscSetClipboard(const std::wstring_view string, | ||
| std::wstring& content, | ||
| bool& queryClipboard) const noexcept | ||
| { | ||
| bool success = false; | ||
| const size_t pos = string.find(';'); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I supposed @DHowett is right, and we could save ourselves a bit of work with a if (_pfnFlushToTerminal != nullptr)
{
return false;
}here. That should cause conpty to pass this through without decoding it once first. That being said, I'm pretty sure setting the clipboard isn't something that's going to be done in a tight loop or end up as any sort of hot path, so I wouldn't block this PR on account of that. |
||
| if (pos != std::wstring_view::npos) | ||
| { | ||
| const std::wstring_view substr = string.substr(pos + 1); | ||
| if (substr == L"?") | ||
| { | ||
| queryClipboard = true; | ||
| success = true; | ||
| } | ||
| else | ||
| { | ||
| try | ||
| { | ||
| auto buffer = CryptographicBuffer::DecodeFromBase64String(winrt::hstring(substr)); | ||
| auto reader = DataReader::FromBuffer(buffer); | ||
| content = reader.ReadString(buffer.Length()); | ||
| success = true; | ||
| } | ||
| catch (...) | ||
zadjii-msft marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return success; | ||
| } | ||
|
|
||
| // Method Description: | ||
| // - Clears our last stored character. The last stored character is the last | ||
| // graphical character we printed, which is reset if any other action is | ||
|
|
||
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.
for naming consistency (when we inevitably get a tool that parses these comments)
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.
(Which is in the works back on the first page of pull requests :P)
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.
Fixed.