diff --git a/doc/cascadia/SettingsSchema.md b/doc/cascadia/SettingsSchema.md index 14c83aeb5c..6522b03650 100644 --- a/doc/cascadia/SettingsSchema.md +++ b/doc/cascadia/SettingsSchema.md @@ -7,6 +7,7 @@ Properties listed below affect the entire window, regardless of the profile sett | -------- | --------- | ---- | ------- | ----------- | | `alwaysShowTabs` | _Required_ | Boolean | `true` | When set to `true`, tabs are always displayed. When set to `false` and `showTabsInTitlebar` is set to `false`, tabs only appear after typing Ctrl + T. | | `copyOnSelect` | Optional | Boolean | `false` | When set to `true`, a selection is immediately copied to your clipboard upon creation. When set to `false`, the selection persists and awaits further action. | +| `copyFormatting` | Optional | Boolean | `false` | When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard. | | `defaultProfile` | _Required_ | String | PowerShell guid | Sets the default profile. Opens by typing Ctrl + T or by clicking the '+' icon. The guid of the desired default profile is used as the value. | | `initialCols` | _Required_ | Integer | `120` | The number of columns displayed in the window upon first load. | | `initialPosition` | Optional | String | `","` | The position of the top left corner of the window upon first load. On a system with multiple displays, these coordinates are relative to the top left of the primary display. If `launchMode` is set to `"maximized"`, the window will be maximized on the monitor specified by those coordinates. | diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 356a474ab4..db6a7e894e 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -277,6 +277,11 @@ "description": "When set to true, a selection is immediately copied to your clipboard upon creation. When set to false, the selection persists and awaits further action.", "type": "boolean" }, + "copyFormatting": { + "default": false, + "description": "When set to `true`, the color and font formatting of selected text is also copied to your clipboard. When set to `false`, only plain text is copied to your clipboard.", + "type": "boolean" + }, "defaultProfile": { "$ref": "#/definitions/ProfileGuid", "description": "Sets the default profile. Opens by clicking the '+' icon or typing the key binding assigned to 'newTab'. The guid of the desired default profile is used as the value." diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index 7d6238cb07..62c814779f 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -32,6 +32,7 @@ static constexpr std::wstring_view TitleLengthTabWidthModeValue{ L"titleLength" static constexpr std::string_view ShowTabsInTitlebarKey{ "showTabsInTitlebar" }; static constexpr std::string_view WordDelimitersKey{ "wordDelimiters" }; static constexpr std::string_view CopyOnSelectKey{ "copyOnSelect" }; +static constexpr std::string_view CopyFormattingKey{ "copyFormatting" }; static constexpr std::string_view LaunchModeKey{ "launchMode" }; static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" }; static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" }; @@ -67,6 +68,7 @@ GlobalAppSettings::GlobalAppSettings() : _tabWidthMode{ TabViewWidthMode::Equal }, _wordDelimiters{ DEFAULT_WORD_DELIMITERS }, _copyOnSelect{ false }, + _copyFormatting{ false }, _launchMode{ LaunchMode::DefaultMode }, _debugFeatures{ debugFeaturesDefault } { @@ -161,6 +163,11 @@ void GlobalAppSettings::SetCopyOnSelect(const bool copyOnSelect) noexcept _copyOnSelect = copyOnSelect; } +bool GlobalAppSettings::GetCopyFormatting() const noexcept +{ + return _copyFormatting; +} + LaunchMode GlobalAppSettings::GetLaunchMode() const noexcept { return _launchMode; @@ -245,6 +252,7 @@ Json::Value GlobalAppSettings::ToJson() const jsonObject[JsonKey(ShowTabsInTitlebarKey)] = _showTabsInTitlebar; jsonObject[JsonKey(WordDelimitersKey)] = winrt::to_string(_wordDelimiters); jsonObject[JsonKey(CopyOnSelectKey)] = _copyOnSelect; + jsonObject[JsonKey(CopyFormattingKey)] = _copyFormatting; jsonObject[JsonKey(LaunchModeKey)] = winrt::to_string(_SerializeLaunchMode(_launchMode)); jsonObject[JsonKey(ThemeKey)] = winrt::to_string(_SerializeTheme(_theme)); jsonObject[JsonKey(TabWidthModeKey)] = winrt::to_string(_SerializeTabWidthMode(_tabWidthMode)); @@ -311,6 +319,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json) JsonUtils::GetBool(json, CopyOnSelectKey, _copyOnSelect); + JsonUtils::GetBool(json, CopyFormattingKey, _copyFormatting); + if (auto launchMode{ json[JsonKey(LaunchModeKey)] }) { _launchMode = _ParseLaunchMode(GetWstringFromJson(launchMode)); diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h index 076b912947..44435c3d57 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.h +++ b/src/cascadia/TerminalApp/GlobalAppSettings.h @@ -68,6 +68,8 @@ public: bool GetCopyOnSelect() const noexcept; void SetCopyOnSelect(const bool copyOnSelect) noexcept; + bool GetCopyFormatting() const noexcept; + std::optional GetInitialX() const noexcept; std::optional GetInitialY() const noexcept; @@ -110,6 +112,7 @@ private: bool _showTabsInTitlebar; std::wstring _wordDelimiters; bool _copyOnSelect; + bool _copyFormatting; winrt::Windows::UI::Xaml::ElementTheme _theme; winrt::Microsoft::UI::Xaml::Controls::TabViewWidthMode _tabWidthMode; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 5df4710db4..a09f0cc846 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1310,18 +1310,21 @@ namespace winrt::TerminalApp::implementation // copy text to dataPack dataPack.SetText(copiedData.Text()); - // copy html to dataPack - const auto htmlData = copiedData.Html(); - if (!htmlData.empty()) + if (_settings->GlobalSettings().GetCopyFormatting()) { - dataPack.SetHtmlFormat(htmlData); - } + // copy html to dataPack + const auto htmlData = copiedData.Html(); + if (!htmlData.empty()) + { + dataPack.SetHtmlFormat(htmlData); + } - // copy rtf data to dataPack - const auto rtfData = copiedData.Rtf(); - if (!rtfData.empty()) - { - dataPack.SetRtf(rtfData); + // copy rtf data to dataPack + const auto rtfData = copiedData.Rtf(); + if (!rtfData.empty()) + { + dataPack.SetRtf(rtfData); + } } try