mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 00:48:23 -06:00
Don't trim bracketed pastes (#19067)
* Moves clipboard writing from `ControlCore` to `TerminalPage`. This requires adding a bunch of event types and logic. This is technically not needed anymore after changing the direction of this PR, but I kept it because it's better. * Add a `WarnAboutMultiLinePaste` enum to differentiate between "paste without warning always/never/if-bracketed-paste-disabled". Closes #13014 Closes https://github.com/microsoft/edit/issues/279 ## Validation Steps Performed * Launch Microsoft Edit and copy text with a trailing newline * Paste it with Ctrl+Shift+V * It's pasted as it was copied ✅ * Changing the setting to "always" always warns ✅ Co-authored-by: Dustin L. Howett <duhowett@microsoft.com>
This commit is contained in:
parent
5b41f14660
commit
e2f3e53064
@ -548,7 +548,9 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
if (const auto& realArgs = args.ActionArgs().try_as<CopyTextArgs>())
|
||||
{
|
||||
const auto handled = _CopyText(realArgs.DismissSelection(), realArgs.SingleLine(), realArgs.WithControlSequences(), realArgs.CopyFormatting());
|
||||
const auto copyFormatting = realArgs.CopyFormatting();
|
||||
const auto format = copyFormatting ? copyFormatting.Value() : _settings.GlobalSettings().CopyFormatting();
|
||||
const auto handled = _CopyText(realArgs.DismissSelection(), realArgs.SingleLine(), realArgs.WithControlSequences(), format);
|
||||
args.Handled(handled);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,121 @@ namespace winrt
|
||||
using VirtualKeyModifiers = Windows::System::VirtualKeyModifiers;
|
||||
}
|
||||
|
||||
namespace clipboard
|
||||
{
|
||||
wil::unique_close_clipboard_call open(HWND hwnd)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// OpenClipboard may fail to acquire the internal lock --> retry.
|
||||
for (DWORD sleep = 10;; sleep *= 2)
|
||||
{
|
||||
if (OpenClipboard(hwnd))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
// 10 iterations
|
||||
if (sleep > 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(sleep);
|
||||
}
|
||||
|
||||
return wil::unique_close_clipboard_call{ success };
|
||||
}
|
||||
|
||||
void write(wil::zwstring_view text, std::string_view html, std::string_view rtf)
|
||||
{
|
||||
static const auto regular = [](const UINT format, const void* src, const size_t bytes) {
|
||||
wil::unique_hglobal handle{ THROW_LAST_ERROR_IF_NULL(GlobalAlloc(GMEM_MOVEABLE, bytes)) };
|
||||
|
||||
const auto locked = GlobalLock(handle.get());
|
||||
memcpy(locked, src, bytes);
|
||||
GlobalUnlock(handle.get());
|
||||
|
||||
THROW_LAST_ERROR_IF_NULL(SetClipboardData(format, handle.get()));
|
||||
handle.release();
|
||||
};
|
||||
static const auto registered = [](const wchar_t* format, const void* src, size_t bytes) {
|
||||
const auto id = RegisterClipboardFormatW(format);
|
||||
if (!id)
|
||||
{
|
||||
LOG_LAST_ERROR();
|
||||
return;
|
||||
}
|
||||
regular(id, src, bytes);
|
||||
};
|
||||
|
||||
EmptyClipboard();
|
||||
|
||||
if (!text.empty())
|
||||
{
|
||||
// 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.
|
||||
regular(CF_UNICODETEXT, text.c_str(), (text.size() + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
if (!html.empty())
|
||||
{
|
||||
registered(L"HTML Format", html.data(), html.size());
|
||||
}
|
||||
|
||||
if (!rtf.empty())
|
||||
{
|
||||
registered(L"Rich Text Format", rtf.data(), rtf.size());
|
||||
}
|
||||
}
|
||||
|
||||
winrt::hstring read()
|
||||
{
|
||||
// This handles most cases of pasting text as the OS converts most formats to CF_UNICODETEXT automatically.
|
||||
if (const auto handle = GetClipboardData(CF_UNICODETEXT))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto str = static_cast<const wchar_t*>(lock.get());
|
||||
if (!str)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto maxLen = GlobalSize(handle) / sizeof(wchar_t);
|
||||
const auto len = wcsnlen(str, maxLen);
|
||||
return winrt::hstring{ str, gsl::narrow_cast<uint32_t>(len) };
|
||||
}
|
||||
|
||||
// We get CF_HDROP when a user copied a file with Ctrl+C in Explorer and pastes that into the terminal (among others).
|
||||
if (const auto handle = GetClipboardData(CF_HDROP))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto drop = static_cast<HDROP>(lock.get());
|
||||
if (!drop)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto cap = DragQueryFileW(drop, 0, nullptr, 0);
|
||||
if (cap == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buffer = winrt::impl::hstring_builder{ cap };
|
||||
const auto len = DragQueryFileW(drop, 0, buffer.data(), cap + 1);
|
||||
if (len == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return buffer.to_hstring();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
} // namespace clipboard
|
||||
|
||||
namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
TerminalPage::TerminalPage(TerminalApp::WindowProperties properties, const TerminalApp::ContentManager& manager) :
|
||||
@ -1793,7 +1908,7 @@ namespace winrt::TerminalApp::implementation
|
||||
{
|
||||
term.RaiseNotice({ this, &TerminalPage::_ControlNoticeRaisedHandler });
|
||||
|
||||
// Add an event handler when the terminal wants to paste data from the Clipboard.
|
||||
term.WriteToClipboard({ get_weak(), &TerminalPage::_copyToClipboard });
|
||||
term.PasteFromClipboard({ this, &TerminalPage::_PasteFromClipboardHandler });
|
||||
|
||||
term.OpenHyperlink({ this, &TerminalPage::_OpenHyperlinkHandler });
|
||||
@ -1815,9 +1930,7 @@ namespace winrt::TerminalApp::implementation
|
||||
});
|
||||
|
||||
term.ShowWindowChanged({ get_weak(), &TerminalPage::_ShowWindowChangedHandler });
|
||||
|
||||
term.SearchMissingCommand({ get_weak(), &TerminalPage::_SearchMissingCommandHandler });
|
||||
|
||||
term.WindowSizeChanged({ get_weak(), &TerminalPage::_WindowSizeChanged });
|
||||
|
||||
// Don't even register for the event if the feature is compiled off.
|
||||
@ -2739,75 +2852,6 @@ namespace winrt::TerminalApp::implementation
|
||||
return dimension;
|
||||
}
|
||||
|
||||
static wil::unique_close_clipboard_call _openClipboard(HWND hwnd)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// OpenClipboard may fail to acquire the internal lock --> retry.
|
||||
for (DWORD sleep = 10;; sleep *= 2)
|
||||
{
|
||||
if (OpenClipboard(hwnd))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
// 10 iterations
|
||||
if (sleep > 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(sleep);
|
||||
}
|
||||
|
||||
return wil::unique_close_clipboard_call{ success };
|
||||
}
|
||||
|
||||
static winrt::hstring _extractClipboard()
|
||||
{
|
||||
// This handles most cases of pasting text as the OS converts most formats to CF_UNICODETEXT automatically.
|
||||
if (const auto handle = GetClipboardData(CF_UNICODETEXT))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto str = static_cast<const wchar_t*>(lock.get());
|
||||
if (!str)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto maxLen = GlobalSize(handle) / sizeof(wchar_t);
|
||||
const auto len = wcsnlen(str, maxLen);
|
||||
return winrt::hstring{ str, gsl::narrow_cast<uint32_t>(len) };
|
||||
}
|
||||
|
||||
// We get CF_HDROP when a user copied a file with Ctrl+C in Explorer and pastes that into the terminal (among others).
|
||||
if (const auto handle = GetClipboardData(CF_HDROP))
|
||||
{
|
||||
const wil::unique_hglobal_locked lock{ handle };
|
||||
const auto drop = static_cast<HDROP>(lock.get());
|
||||
if (!drop)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto cap = DragQueryFileW(drop, 0, nullptr, 0);
|
||||
if (cap == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
auto buffer = winrt::impl::hstring_builder{ cap };
|
||||
const auto len = DragQueryFileW(drop, 0, buffer.data(), cap + 1);
|
||||
if (len == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return buffer.to_hstring();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// Function Description:
|
||||
// - This function is called when the `TermControl` requests that we send
|
||||
// it the clipboard's content.
|
||||
@ -2827,36 +2871,51 @@ namespace winrt::TerminalApp::implementation
|
||||
const auto weakThis = get_weak();
|
||||
const auto dispatcher = Dispatcher();
|
||||
const auto globalSettings = _settings.GlobalSettings();
|
||||
const auto bracketedPaste = eventArgs.BracketedPasteEnabled();
|
||||
|
||||
// GetClipboardData might block for up to 30s for delay-rendered contents.
|
||||
co_await winrt::resume_background();
|
||||
|
||||
winrt::hstring text;
|
||||
if (const auto clipboard = _openClipboard(nullptr))
|
||||
if (const auto clipboard = clipboard::open(nullptr))
|
||||
{
|
||||
text = _extractClipboard();
|
||||
text = clipboard::read();
|
||||
}
|
||||
|
||||
if (globalSettings.TrimPaste())
|
||||
if (!bracketedPaste && globalSettings.TrimPaste())
|
||||
{
|
||||
text = { Utils::TrimPaste(text) };
|
||||
if (text.empty())
|
||||
{
|
||||
// Text is all white space, nothing to paste
|
||||
co_return;
|
||||
}
|
||||
text = winrt::hstring{ Utils::TrimPaste(text) };
|
||||
}
|
||||
|
||||
if (text.empty())
|
||||
{
|
||||
co_return;
|
||||
}
|
||||
|
||||
bool warnMultiLine = false;
|
||||
switch (globalSettings.WarnAboutMultiLinePaste())
|
||||
{
|
||||
case WarnAboutMultiLinePaste::Automatic:
|
||||
// NOTE that this is unsafe, because a shell that doesn't support bracketed paste
|
||||
// will allow an attacker to enable the mode, not realize that, and then accept
|
||||
// the paste as if it was a series of legitimate commands. See GH#13014.
|
||||
warnMultiLine = !bracketedPaste;
|
||||
break;
|
||||
case WarnAboutMultiLinePaste::Always:
|
||||
warnMultiLine = true;
|
||||
break;
|
||||
default:
|
||||
warnMultiLine = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the requesting terminal is in bracketed paste mode, then we don't need to warn about a multi-line paste.
|
||||
auto warnMultiLine = globalSettings.WarnAboutMultiLinePaste() && !eventArgs.BracketedPasteEnabled();
|
||||
if (warnMultiLine)
|
||||
{
|
||||
const auto isNewLineLambda = [](auto c) { return c == L'\n' || c == L'\r'; };
|
||||
const auto hasNewLine = std::find_if(text.cbegin(), text.cend(), isNewLineLambda) != text.cend();
|
||||
warnMultiLine = hasNewLine;
|
||||
const std::wstring_view view{ text };
|
||||
warnMultiLine = view.find_first_of(L"\r\n") != std::wstring_view::npos;
|
||||
}
|
||||
|
||||
constexpr const std::size_t minimumSizeForWarning = 1024 * 5; // 5 KiB
|
||||
constexpr std::size_t minimumSizeForWarning = 1024 * 5; // 5 KiB
|
||||
const auto warnLargeText = text.size() > minimumSizeForWarning && globalSettings.WarnAboutLargePaste();
|
||||
|
||||
if (warnMultiLine || warnLargeText)
|
||||
@ -2866,7 +2925,7 @@ namespace winrt::TerminalApp::implementation
|
||||
if (const auto strongThis = weakThis.get())
|
||||
{
|
||||
// We have to initialize the dialog here to be able to change the text of the text block within it
|
||||
FindName(L"MultiLinePasteDialog").try_as<WUX::Controls::ContentDialog>();
|
||||
std::ignore = FindName(L"MultiLinePasteDialog");
|
||||
ClipboardText().Text(text);
|
||||
|
||||
// The vertical offset on the scrollbar does not reset automatically, so reset it manually
|
||||
@ -3047,7 +3106,7 @@ namespace winrt::TerminalApp::implementation
|
||||
// - formats: dictate which formats need to be copied
|
||||
// Return Value:
|
||||
// - true iff we we able to copy text (if a selection was active)
|
||||
bool TerminalPage::_CopyText(const bool dismissSelection, const bool singleLine, const bool withControlSequences, const Windows::Foundation::IReference<CopyFormat>& formats)
|
||||
bool TerminalPage::_CopyText(const bool dismissSelection, const bool singleLine, const bool withControlSequences, const CopyFormat formats)
|
||||
{
|
||||
if (const auto& control{ _GetActiveControl() })
|
||||
{
|
||||
@ -3190,6 +3249,21 @@ namespace winrt::TerminalApp::implementation
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalPage::_copyToClipboard(const IInspectable, const WriteToClipboardEventArgs args) const
|
||||
{
|
||||
if (const auto clipboard = clipboard::open(_hostingHwnd.value_or(nullptr)))
|
||||
{
|
||||
const auto plain = args.Plain();
|
||||
const auto html = args.Html();
|
||||
const auto rtf = args.Rtf();
|
||||
|
||||
clipboard::write(
|
||||
{ plain.data(), plain.size() },
|
||||
{ reinterpret_cast<const char*>(html.data()), html.size() },
|
||||
{ reinterpret_cast<const char*>(rtf.data()), rtf.size() });
|
||||
}
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Paste text from the Windows Clipboard to the focused terminal
|
||||
void TerminalPage::_PasteText()
|
||||
|
||||
@ -413,10 +413,11 @@ namespace winrt::TerminalApp::implementation
|
||||
bool _IsUriSupported(const winrt::Windows::Foundation::Uri& parsedUri);
|
||||
|
||||
void _ShowCouldNotOpenDialog(winrt::hstring reason, winrt::hstring uri);
|
||||
bool _CopyText(const bool dismissSelection, const bool singleLine, const bool withControlSequences, const Windows::Foundation::IReference<Microsoft::Terminal::Control::CopyFormat>& formats);
|
||||
bool _CopyText(bool dismissSelection, bool singleLine, bool withControlSequences, Microsoft::Terminal::Control::CopyFormat formats);
|
||||
|
||||
safe_void_coroutine _SetTaskbarProgressHandler(const IInspectable sender, const IInspectable eventArgs);
|
||||
|
||||
void _copyToClipboard(IInspectable, Microsoft::Terminal::Control::WriteToClipboardEventArgs args) const;
|
||||
void _PasteText();
|
||||
|
||||
safe_void_coroutine _ControlNoticeRaisedHandler(const IInspectable sender, const Microsoft::Terminal::Control::NoticeEventArgs eventArgs);
|
||||
|
||||
@ -104,8 +104,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// GH#8969: pre-seed working directory to prevent potential races
|
||||
_terminal->SetWorkingDirectory(_settings->StartingDirectory());
|
||||
|
||||
auto pfnCopyToClipboard = [this](auto&& PH1) { _terminalCopyToClipboard(std::forward<decltype(PH1)>(PH1)); };
|
||||
_terminal->SetCopyToClipboardCallback(pfnCopyToClipboard);
|
||||
_terminal->SetCopyToClipboardCallback([this](wil::zwstring_view wstr) {
|
||||
WriteToClipboard.raise(*this, winrt::make<WriteToClipboardEventArgs>(winrt::hstring{ std::wstring_view{ wstr } }, std::string{}, std::string{}));
|
||||
});
|
||||
|
||||
auto pfnWarningBell = [this] { _terminalWarningBell(); };
|
||||
_terminal->SetWarningBellCallback(pfnWarningBell);
|
||||
@ -599,7 +600,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
else if (vkey == VK_RETURN && !mods.IsCtrlPressed() && !mods.IsAltPressed())
|
||||
{
|
||||
// [Shift +] Enter --> copy text
|
||||
CopySelectionToClipboard(mods.IsShiftPressed(), false, nullptr);
|
||||
CopySelectionToClipboard(mods.IsShiftPressed(), false, _settings->CopyFormatting());
|
||||
_terminal->ClearSelection();
|
||||
_updateSelectionUI();
|
||||
return true;
|
||||
@ -1263,89 +1264,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_updateSelectionUI();
|
||||
}
|
||||
|
||||
static wil::unique_close_clipboard_call _openClipboard(HWND hwnd)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
// OpenClipboard may fail to acquire the internal lock --> retry.
|
||||
for (DWORD sleep = 10;; sleep *= 2)
|
||||
{
|
||||
if (OpenClipboard(hwnd))
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
// 10 iterations
|
||||
if (sleep > 10000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Sleep(sleep);
|
||||
}
|
||||
|
||||
return wil::unique_close_clipboard_call{ success };
|
||||
}
|
||||
|
||||
static void _copyToClipboard(const UINT format, const void* src, const size_t bytes)
|
||||
{
|
||||
wil::unique_hglobal handle{ THROW_LAST_ERROR_IF_NULL(GlobalAlloc(GMEM_MOVEABLE, bytes)) };
|
||||
|
||||
const auto locked = GlobalLock(handle.get());
|
||||
memcpy(locked, src, bytes);
|
||||
GlobalUnlock(handle.get());
|
||||
|
||||
THROW_LAST_ERROR_IF_NULL(SetClipboardData(format, handle.get()));
|
||||
handle.release();
|
||||
}
|
||||
|
||||
static void _copyToClipboardRegisteredFormat(const wchar_t* format, const void* src, size_t bytes)
|
||||
{
|
||||
const auto id = RegisterClipboardFormatW(format);
|
||||
if (!id)
|
||||
{
|
||||
LOG_LAST_ERROR();
|
||||
return;
|
||||
}
|
||||
_copyToClipboard(id, src, bytes);
|
||||
}
|
||||
|
||||
static void copyToClipboard(wil::zwstring_view text, std::string_view html, std::string_view rtf)
|
||||
{
|
||||
const auto clipboard = _openClipboard(nullptr);
|
||||
if (!clipboard)
|
||||
{
|
||||
LOG_LAST_ERROR();
|
||||
return;
|
||||
}
|
||||
|
||||
EmptyClipboard();
|
||||
|
||||
if (!text.empty())
|
||||
{
|
||||
// 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));
|
||||
}
|
||||
|
||||
if (!html.empty())
|
||||
{
|
||||
_copyToClipboardRegisteredFormat(L"HTML Format", html.data(), html.size());
|
||||
}
|
||||
|
||||
if (!rtf.empty())
|
||||
{
|
||||
_copyToClipboardRegisteredFormat(L"Rich Text Format", rtf.data(), rtf.size());
|
||||
}
|
||||
}
|
||||
|
||||
// Called when the Terminal wants to set something to the clipboard, i.e.
|
||||
// when an OSC 52 is emitted.
|
||||
void ControlCore::_terminalCopyToClipboard(wil::zwstring_view wstr)
|
||||
{
|
||||
copyToClipboard(wstr, {}, {});
|
||||
}
|
||||
|
||||
// Method Description:
|
||||
// - Given a copy-able selection, get the selected text from the buffer and send it to the
|
||||
// Windows Clipboard (CascadiaWin32:main.cpp).
|
||||
@ -1356,7 +1274,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// if we should defer which formats are copied to the global setting
|
||||
bool ControlCore::CopySelectionToClipboard(bool singleLine,
|
||||
bool withControlSequences,
|
||||
const Windows::Foundation::IReference<CopyFormat>& formats)
|
||||
const CopyFormat formats)
|
||||
{
|
||||
::Microsoft::Terminal::Core::Terminal::TextCopyData payload;
|
||||
{
|
||||
@ -1368,19 +1286,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
return false;
|
||||
}
|
||||
|
||||
// use action's copyFormatting if it's present, else fall back to globally
|
||||
// set copyFormatting.
|
||||
const auto copyFormats = formats != nullptr ? formats.Value() : _settings->CopyFormatting();
|
||||
|
||||
const auto copyHtml = WI_IsFlagSet(copyFormats, CopyFormat::HTML);
|
||||
const auto copyRtf = WI_IsFlagSet(copyFormats, CopyFormat::RTF);
|
||||
const auto copyHtml = WI_IsFlagSet(formats, CopyFormat::HTML);
|
||||
const auto copyRtf = WI_IsFlagSet(formats, CopyFormat::RTF);
|
||||
|
||||
// extract text from buffer
|
||||
// RetrieveSelectedTextFromBuffer will lock while it's reading
|
||||
payload = _terminal->RetrieveSelectedTextFromBuffer(singleLine, withControlSequences, copyHtml, copyRtf);
|
||||
}
|
||||
|
||||
copyToClipboard(payload.plainText, payload.html, payload.rtf);
|
||||
WriteToClipboard.raise(
|
||||
*this,
|
||||
winrt::make<WriteToClipboardEventArgs>(
|
||||
winrt::hstring{ payload.plainText },
|
||||
std::move(payload.html),
|
||||
std::move(payload.rtf)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -124,7 +124,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
void SendInput(std::wstring_view wstr);
|
||||
void PasteText(const winrt::hstring& hstr);
|
||||
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const Windows::Foundation::IReference<CopyFormat>& formats);
|
||||
bool CopySelectionToClipboard(bool singleLine, bool withControlSequences, const CopyFormat formats);
|
||||
void SelectAll();
|
||||
void ClearSelection();
|
||||
bool ToggleBlockSelection();
|
||||
@ -277,6 +277,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
til::typed_event<IInspectable, Control::FontSizeChangedArgs> FontSizeChanged;
|
||||
|
||||
til::typed_event<IInspectable, Control::TitleChangedEventArgs> TitleChanged;
|
||||
til::typed_event<IInspectable, Control::WriteToClipboardEventArgs> WriteToClipboard;
|
||||
til::typed_event<> WarningBell;
|
||||
til::typed_event<> TabColorChanged;
|
||||
til::typed_event<> BackgroundColorChanged;
|
||||
@ -325,7 +326,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
void _sendInputToConnection(std::wstring_view wstr);
|
||||
|
||||
#pragma region TerminalCoreCallbacks
|
||||
void _terminalCopyToClipboard(wil::zwstring_view wstr);
|
||||
void _terminalWarningBell();
|
||||
void _terminalTitleChanged(std::wstring_view wstr);
|
||||
void _terminalScrollPositionChanged(const int viewTop,
|
||||
|
||||
@ -185,6 +185,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
// These events are called from some background thread
|
||||
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, WriteToClipboardEventArgs> WriteToClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> WarningBell;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> TabColorChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> BackgroundColorChanged;
|
||||
|
||||
@ -199,7 +199,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// if we should defer which formats are copied to the global setting
|
||||
bool ControlInteractivity::CopySelectionToClipboard(bool singleLine,
|
||||
bool withControlSequences,
|
||||
const Windows::Foundation::IReference<CopyFormat>& formats)
|
||||
const CopyFormat formats)
|
||||
{
|
||||
if (_core)
|
||||
{
|
||||
@ -316,7 +316,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
else
|
||||
{
|
||||
// Try to copy the text and clear the selection
|
||||
const auto successfulCopy = CopySelectionToClipboard(shiftEnabled, false, nullptr);
|
||||
const auto successfulCopy = CopySelectionToClipboard(shiftEnabled, false, _core->Settings().CopyFormatting());
|
||||
_core->ClearSelection();
|
||||
if (_core->CopyOnSelect() || !successfulCopy)
|
||||
{
|
||||
@ -461,7 +461,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// IMPORTANT!
|
||||
// DO NOT clear the selection here!
|
||||
// Otherwise, the selection will be cleared immediately after you make it.
|
||||
CopySelectionToClipboard(false, false, nullptr);
|
||||
CopySelectionToClipboard(false, false, _core->Settings().CopyFormatting());
|
||||
}
|
||||
|
||||
_singleClickTouchdownPos = std::nullopt;
|
||||
|
||||
@ -84,7 +84,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
bool CopySelectionToClipboard(bool singleLine,
|
||||
bool withControlSequences,
|
||||
const Windows::Foundation::IReference<CopyFormat>& formats);
|
||||
const CopyFormat formats);
|
||||
void RequestPasteTextFromClipboard();
|
||||
void SetEndSelectionPoint(const Core::Point pixelPosition);
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ namespace Microsoft.Terminal.Control
|
||||
|
||||
InteractivityAutomationPeer OnCreateAutomationPeer();
|
||||
|
||||
Boolean CopySelectionToClipboard(Boolean singleLine, Boolean withControlSequences, Windows.Foundation.IReference<CopyFormat> formats);
|
||||
Boolean CopySelectionToClipboard(Boolean singleLine, Boolean withControlSequences, CopyFormat formats);
|
||||
void RequestPasteTextFromClipboard();
|
||||
void SetEndSelectionPoint(Microsoft.Terminal.Core.Point point);
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "FontSizeChangedArgs.g.cpp"
|
||||
#include "TitleChangedEventArgs.g.cpp"
|
||||
#include "ContextMenuRequestedEventArgs.g.cpp"
|
||||
#include "WriteToClipboardEventArgs.g.cpp"
|
||||
#include "PasteFromClipboardEventArgs.g.cpp"
|
||||
#include "OpenHyperlinkEventArgs.g.cpp"
|
||||
#include "NoticeEventArgs.g.cpp"
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "FontSizeChangedArgs.g.h"
|
||||
#include "TitleChangedEventArgs.g.h"
|
||||
#include "ContextMenuRequestedEventArgs.g.h"
|
||||
#include "WriteToClipboardEventArgs.g.h"
|
||||
#include "PasteFromClipboardEventArgs.g.h"
|
||||
#include "OpenHyperlinkEventArgs.g.h"
|
||||
#include "NoticeEventArgs.g.h"
|
||||
@ -56,6 +57,32 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
WINRT_PROPERTY(winrt::Windows::Foundation::Point, Position);
|
||||
};
|
||||
|
||||
struct WriteToClipboardEventArgs : WriteToClipboardEventArgsT<WriteToClipboardEventArgs>
|
||||
{
|
||||
WriteToClipboardEventArgs(winrt::hstring&& plain, std::string&& html, std::string&& rtf) :
|
||||
_plain(std::move(plain)),
|
||||
_html(std::move(html)),
|
||||
_rtf(std::move(rtf))
|
||||
{
|
||||
}
|
||||
|
||||
winrt::hstring Plain() const noexcept { return _plain; }
|
||||
winrt::com_array<uint8_t> Html() noexcept { return _cast(_html); }
|
||||
winrt::com_array<uint8_t> Rtf() noexcept { return _cast(_rtf); }
|
||||
|
||||
private:
|
||||
static winrt::com_array<uint8_t> _cast(const std::string& str)
|
||||
{
|
||||
const auto beg = reinterpret_cast<const uint8_t*>(str.data());
|
||||
const auto len = str.size();
|
||||
return { beg, beg + len };
|
||||
}
|
||||
|
||||
winrt::hstring _plain;
|
||||
std::string _html;
|
||||
std::string _rtf;
|
||||
};
|
||||
|
||||
struct PasteFromClipboardEventArgs : public PasteFromClipboardEventArgsT<PasteFromClipboardEventArgs>
|
||||
{
|
||||
public:
|
||||
|
||||
@ -6,6 +6,7 @@ namespace Microsoft.Terminal.Control
|
||||
[flags]
|
||||
enum CopyFormat
|
||||
{
|
||||
None = 0x0,
|
||||
HTML = 0x1,
|
||||
RTF = 0x2,
|
||||
All = 0xffffffff
|
||||
@ -31,6 +32,13 @@ namespace Microsoft.Terminal.Control
|
||||
AlphanumericHalfWidth,
|
||||
};
|
||||
|
||||
enum WarnAboutMultiLinePaste
|
||||
{
|
||||
Automatic,
|
||||
Always,
|
||||
Never,
|
||||
};
|
||||
|
||||
runtimeclass FontSizeChangedArgs
|
||||
{
|
||||
Int32 Width { get; };
|
||||
@ -47,6 +55,13 @@ namespace Microsoft.Terminal.Control
|
||||
String Title;
|
||||
}
|
||||
|
||||
runtimeclass WriteToClipboardEventArgs
|
||||
{
|
||||
String Plain { get; }; // UTF-16, as required by CF_UNICODETEXT
|
||||
byte[] Html { get; }; // UTF-8, as required by "HTML Format"
|
||||
byte[] Rtf { get; }; // UTF-8, as required by "Rich Text Format"
|
||||
}
|
||||
|
||||
runtimeclass PasteFromClipboardEventArgs
|
||||
{
|
||||
void HandleClipboardData(String data);
|
||||
|
||||
@ -330,6 +330,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
_revokers.RestartTerminalRequested = _core.RestartTerminalRequested(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleRestartTerminalRequested });
|
||||
_revokers.SearchMissingCommand = _core.SearchMissingCommand(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleSearchMissingCommand });
|
||||
_revokers.WindowSizeChanged = _core.WindowSizeChanged(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleWindowSizeChanged });
|
||||
_revokers.WriteToClipboard = _core.WriteToClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubbleWriteToClipboard });
|
||||
|
||||
_revokers.PasteFromClipboard = _interactivity.PasteFromClipboard(winrt::auto_revoke, { get_weak(), &TermControl::_bubblePasteFromClipboard });
|
||||
|
||||
@ -2634,7 +2635,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
// - withControlSequences: if enabled, the copied plain text contains color/style ANSI escape codes from the selection
|
||||
// - formats: which formats to copy (defined by action's CopyFormatting arg). nullptr
|
||||
// if we should defer which formats are copied to the global setting
|
||||
bool TermControl::CopySelectionToClipboard(bool dismissSelection, bool singleLine, bool withControlSequences, const Windows::Foundation::IReference<CopyFormat>& formats)
|
||||
bool TermControl::CopySelectionToClipboard(bool dismissSelection, bool singleLine, bool withControlSequences, const CopyFormat formats)
|
||||
{
|
||||
if (_IsClosing())
|
||||
{
|
||||
@ -4153,7 +4154,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
const IInspectable& /*args*/)
|
||||
{
|
||||
// formats = nullptr -> copy all formats
|
||||
_interactivity.CopySelectionToClipboard(false, false, nullptr);
|
||||
_interactivity.CopySelectionToClipboard(false, false, _core.Settings().CopyFormatting());
|
||||
ContextMenu().Hide();
|
||||
SelectionContextMenu().Hide();
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
|
||||
hstring GetProfileName() const;
|
||||
|
||||
bool CopySelectionToClipboard(bool dismissSelection, bool singleLine, bool withControlSequences, const Windows::Foundation::IReference<CopyFormat>& formats);
|
||||
bool CopySelectionToClipboard(bool dismissSelection, bool singleLine, bool withControlSequences, const CopyFormat formats);
|
||||
void PasteTextFromClipboard();
|
||||
void SelectAll();
|
||||
bool ToggleBlockSelection();
|
||||
@ -227,8 +227,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(CloseTerminalRequested, IInspectable, IInspectable);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(CompletionsChanged, IInspectable, Control::CompletionsChangedEventArgs);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(RestartTerminalRequested, IInspectable, IInspectable);
|
||||
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(WriteToClipboard, IInspectable, Control::WriteToClipboardEventArgs);
|
||||
BUBBLED_FORWARDED_TYPED_EVENT(PasteFromClipboard, IInspectable, Control::PasteFromClipboardEventArgs);
|
||||
|
||||
// clang-format on
|
||||
|
||||
@ -463,6 +463,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
|
||||
Control::ControlCore::UpdateSelectionMarkers_revoker UpdateSelectionMarkers;
|
||||
Control::ControlCore::OpenHyperlink_revoker coreOpenHyperlink;
|
||||
Control::ControlCore::TitleChanged_revoker TitleChanged;
|
||||
Control::ControlCore::WriteToClipboard_revoker WriteToClipboard;
|
||||
Control::ControlCore::TabColorChanged_revoker TabColorChanged;
|
||||
Control::ControlCore::TaskbarProgressChanged_revoker TaskbarProgressChanged;
|
||||
Control::ControlCore::ConnectionStateChanged_revoker ConnectionStateChanged;
|
||||
|
||||
@ -53,6 +53,7 @@ namespace Microsoft.Terminal.Control
|
||||
Microsoft.Terminal.Control.IControlSettings Settings { get; };
|
||||
|
||||
event Windows.Foundation.TypedEventHandler<Object, TitleChangedEventArgs> TitleChanged;
|
||||
event Windows.Foundation.TypedEventHandler<Object, WriteToClipboardEventArgs> WriteToClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, PasteFromClipboardEventArgs> PasteFromClipboard;
|
||||
event Windows.Foundation.TypedEventHandler<Object, OpenHyperlinkEventArgs> OpenHyperlink;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
|
||||
@ -87,7 +88,7 @@ namespace Microsoft.Terminal.Control
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> CloseTerminalRequested;
|
||||
event Windows.Foundation.TypedEventHandler<Object, Object> RestartTerminalRequested;
|
||||
|
||||
Boolean CopySelectionToClipboard(Boolean dismissSelection, Boolean singleLine, Boolean withControlSequences, Windows.Foundation.IReference<CopyFormat> formats);
|
||||
Boolean CopySelectionToClipboard(Boolean dismissSelection, Boolean singleLine, Boolean withControlSequences, CopyFormat formats);
|
||||
void PasteTextFromClipboard();
|
||||
void SelectAll();
|
||||
Boolean ToggleBlockSelection();
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
#include "Interaction.h"
|
||||
#include "Interaction.g.cpp"
|
||||
|
||||
#include "EnumEntry.h"
|
||||
|
||||
using namespace winrt::Windows::UI::Xaml::Navigation;
|
||||
using namespace winrt::Microsoft::Terminal::Settings::Model;
|
||||
|
||||
@ -13,6 +15,8 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
Interaction::Interaction()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
INITIALIZE_BINDABLE_ENUM_SETTING(WarnAboutMultiLinePaste, WarnAboutMultiLinePaste, winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste, L"Globals_WarnAboutMultiLinePaste", L"Content");
|
||||
}
|
||||
|
||||
void Interaction::OnNavigatedTo(const NavigationEventArgs& e)
|
||||
|
||||
@ -16,6 +16,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
|
||||
|
||||
til::property_changed_event PropertyChanged;
|
||||
WINRT_OBSERVABLE_PROPERTY(Editor::InteractionViewModel, ViewModel, PropertyChanged.raise, nullptr);
|
||||
GETSET_BINDABLE_ENUM_SETTING(WarnAboutMultiLinePaste, winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste, ViewModel().WarnAboutMultiLinePaste);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -9,5 +9,8 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
{
|
||||
Interaction();
|
||||
InteractionViewModel ViewModel { get; };
|
||||
|
||||
IInspectable CurrentWarnAboutMultiLinePaste;
|
||||
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> WarnAboutMultiLinePasteList { get; };
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,8 +142,11 @@
|
||||
|
||||
<!-- Multi Line Paste Warning -->
|
||||
<local:SettingContainer x:Uid="Globals_WarnAboutMultiLinePaste">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.WarnAboutMultiLinePaste, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
|
||||
<ComboBox AutomationProperties.AccessibilityView="Content"
|
||||
ItemTemplate="{StaticResource EnumComboBoxTemplate}"
|
||||
ItemsSource="{x:Bind WarnAboutMultiLinePasteList}"
|
||||
SelectedItem="{x:Bind CurrentWarnAboutMultiLinePaste, Mode=TwoWay}"
|
||||
Style="{StaticResource ComboBoxSettingStyle}" />
|
||||
</local:SettingContainer>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
@ -30,7 +30,7 @@ namespace Microsoft.Terminal.Settings.Editor
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ConfirmCloseAllTabs);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, InputServiceWarning);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, WarnAboutLargePaste);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, WarnAboutMultiLinePaste);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Microsoft.Terminal.Control.WarnAboutMultiLinePaste, WarnAboutMultiLinePaste);
|
||||
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, EnableColorSelection);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1924,10 +1924,26 @@
|
||||
<value>Warn when "Touch Keyboard and Handwriting Panel Service" is disabled</value>
|
||||
</data>
|
||||
<data name="Globals_WarnAboutLargePaste.Header" xml:space="preserve">
|
||||
<value>Warn when trying to paste more than 5 KiB of characters</value>
|
||||
<value>Warn when pasting more than 5 KiB</value>
|
||||
</data>
|
||||
<data name="Globals_WarnAboutMultiLinePaste.Header" xml:space="preserve">
|
||||
<value>Warn when trying to paste a "new line" character</value>
|
||||
<value>Warn when pasting newlines</value>
|
||||
</data>
|
||||
<data name="Globals_WarnAboutMultiLinePaste.HelpText" xml:space="preserve">
|
||||
<value>If your shell does not support "bracketed paste" mode, we recommend setting this to "Always" for security reasons.</value>
|
||||
<comment>"bracketed paste" is a technical term referring to escape sequences. "Always" is a setting, as in "Always VS Never".</comment>
|
||||
</data>
|
||||
<data name="Globals_WarnAboutMultiLinePasteAutomatic.Content" xml:space="preserve">
|
||||
<value>Only if "bracketed paste" is disabled</value>
|
||||
<comment>"bracketed paste" is a technical term referring to terminal escape sequences.</comment>
|
||||
</data>
|
||||
<data name="Globals_WarnAboutMultiLinePasteAlways.Content" xml:space="preserve">
|
||||
<value>Always</value>
|
||||
<comment>As in: Always VS Never</comment>
|
||||
</data>
|
||||
<data name="Globals_WarnAboutMultiLinePasteNever.Content" xml:space="preserve">
|
||||
<value>Never</value>
|
||||
<comment>As in: Always VS Never</comment>
|
||||
</data>
|
||||
<data name="Settings_PortableModeNote.Text" xml:space="preserve">
|
||||
<value>Windows Terminal is running in portable mode.</value>
|
||||
|
||||
@ -42,6 +42,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Core::MatchMode, MatchMode);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::GraphicsAPI, GraphicsAPI);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::TextMeasurement, TextMeasurement);
|
||||
DEFINE_ENUM_MAP(Microsoft::Terminal::Control::WarnAboutMultiLinePaste, WarnAboutMultiLinePaste);
|
||||
|
||||
// Profile Settings
|
||||
DEFINE_ENUM_MAP(Model::CloseOnExitMode, CloseOnExitMode);
|
||||
|
||||
@ -38,6 +38,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Core::MatchMode> MatchMode();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::GraphicsAPI> GraphicsAPI();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::TextMeasurement> TextMeasurement();
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste> WarnAboutMultiLinePaste();
|
||||
|
||||
// Profile Settings
|
||||
static winrt::Windows::Foundation::Collections::IMap<winrt::hstring, CloseOnExitMode> CloseOnExitMode();
|
||||
|
||||
@ -20,6 +20,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Core.MatchMode> MatchMode { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.GraphicsAPI> GraphicsAPI { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.TextMeasurement> TextMeasurement { get; };
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Control.WarnAboutMultiLinePaste> WarnAboutMultiLinePaste { get; };
|
||||
|
||||
// Profile Settings
|
||||
static Windows.Foundation.Collections.IMap<String, Microsoft.Terminal.Settings.Model.CloseOnExitMode> CloseOnExitMode { get; };
|
||||
|
||||
@ -70,7 +70,7 @@ namespace Microsoft.Terminal.Settings.Model
|
||||
INHERITABLE_SETTING(Boolean, InputServiceWarning);
|
||||
INHERITABLE_SETTING(Microsoft.Terminal.Control.CopyFormat, CopyFormatting);
|
||||
INHERITABLE_SETTING(Boolean, WarnAboutLargePaste);
|
||||
INHERITABLE_SETTING(Boolean, WarnAboutMultiLinePaste);
|
||||
INHERITABLE_SETTING(Microsoft.Terminal.Control.WarnAboutMultiLinePaste, WarnAboutMultiLinePaste);
|
||||
INHERITABLE_SETTING(Boolean, TrimPaste);
|
||||
INHERITABLE_SETTING(LaunchPosition, InitialPosition);
|
||||
INHERITABLE_SETTING(Boolean, CenterOnLaunch);
|
||||
|
||||
@ -46,7 +46,7 @@ Author(s):
|
||||
X(bool, InputServiceWarning, "warning.inputService", true) \
|
||||
X(winrt::Microsoft::Terminal::Control::CopyFormat, CopyFormatting, "copyFormatting", 0) \
|
||||
X(bool, WarnAboutLargePaste, "warning.largePaste", true) \
|
||||
X(bool, WarnAboutMultiLinePaste, "warning.multiLinePaste", true) \
|
||||
X(winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste, WarnAboutMultiLinePaste, "warning.multiLinePaste", winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste::Automatic) \
|
||||
X(Model::LaunchPosition, InitialPosition, "initialPosition", nullptr, nullptr) \
|
||||
X(bool, CenterOnLaunch, "centerOnLaunch", false) \
|
||||
X(Model::FirstWindowPreference, FirstWindowPreference, "firstWindowPreference", FirstWindowPreference::DefaultProfile) \
|
||||
|
||||
@ -841,3 +841,29 @@ JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::PathTranslationStyle)
|
||||
pair_type{ "mingw", ValueType::MinGW },
|
||||
};
|
||||
};
|
||||
|
||||
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste)
|
||||
{
|
||||
JSON_MAPPINGS(3) = {
|
||||
pair_type{ "automatic", ValueType::Automatic },
|
||||
pair_type{ "always", ValueType::Always },
|
||||
pair_type{ "never", ValueType::Never },
|
||||
};
|
||||
|
||||
// Override mapping parser to add boolean parsing
|
||||
::winrt::Microsoft::Terminal::Control::WarnAboutMultiLinePaste FromJson(const Json::Value& json)
|
||||
{
|
||||
if (json.isBool())
|
||||
{
|
||||
return json.asBool() ? ValueType::Automatic : ValueType::Never;
|
||||
}
|
||||
return EnumMapper::FromJson(json);
|
||||
}
|
||||
|
||||
bool CanConvert(const Json::Value& json)
|
||||
{
|
||||
return EnumMapper::CanConvert(json) || json.isBool();
|
||||
}
|
||||
|
||||
using EnumMapper::TypeDescription;
|
||||
};
|
||||
|
||||
@ -128,7 +128,7 @@ namespace SettingsModelUnitTests
|
||||
"warning.confirmCloseAllTabs" : true,
|
||||
"warning.inputService" : true,
|
||||
"warning.largePaste" : true,
|
||||
"warning.multiLinePaste" : true,
|
||||
"warning.multiLinePaste" : "automatic",
|
||||
|
||||
"actions": [],
|
||||
"keybindings": []
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user