From 5d9d11707f7f399e2f86443afba0fae442cc91e1 Mon Sep 17 00:00:00 2001 From: Robert Jordan Date: Sat, 13 Jul 2019 12:27:36 -0400 Subject: [PATCH 1/5] Implement base background image alignment settings TerminalSettings now has two new properties: * BackgroundImageHorizontalAlignment * BackgroundImageVerticalAlignment These properties are used in TermControl::_InitializeBackgroundBrush to specify the alignment for TermControl::_bgImageLayer. This is a base commit that will split into two possible branches: * Use one setting in profiles.json: "backgroundImageAlignment" * Use two settings in profiles.json: "backgroundImageHorizontal/VerticalAlignment" --- src/cascadia/TerminalControl/TermControl.cpp | 6 ++--- .../TerminalSettings/IControlSettings.idl | 2 ++ .../TerminalSettings/TerminalSettings.cpp | 22 +++++++++++++++++++ .../TerminalSettings/terminalsettings.h | 6 +++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 6a8c3b8866e..24d8c40f27b 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -272,13 +272,13 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation // internet. Media::Imaging::BitmapImage image(imageUri); _bgImageLayer.Source(image); - _bgImageLayer.HorizontalAlignment(HorizontalAlignment::Center); - _bgImageLayer.VerticalAlignment(VerticalAlignment::Center); } - // Apply stretch and opacity settings + // Apply stretch, opacity and alignment settings _bgImageLayer.Stretch(_settings.BackgroundImageStretchMode()); _bgImageLayer.Opacity(_settings.BackgroundImageOpacity()); + _bgImageLayer.HorizontalAlignment(_settings.BackgroundImageHorizontalAlignment()); + _bgImageLayer.VerticalAlignment(_settings.BackgroundImageVerticalAlignment()); } else { diff --git a/src/cascadia/TerminalSettings/IControlSettings.idl b/src/cascadia/TerminalSettings/IControlSettings.idl index e0ad1278753..e706f82b183 100644 --- a/src/cascadia/TerminalSettings/IControlSettings.idl +++ b/src/cascadia/TerminalSettings/IControlSettings.idl @@ -37,5 +37,7 @@ namespace Microsoft.Terminal.Settings String BackgroundImage; Double BackgroundImageOpacity; Windows.UI.Xaml.Media.Stretch BackgroundImageStretchMode; + Windows.UI.Xaml.HorizontalAlignment BackgroundImageHorizontalAlignment; + Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment; }; } diff --git a/src/cascadia/TerminalSettings/TerminalSettings.cpp b/src/cascadia/TerminalSettings/TerminalSettings.cpp index 70e2a2a6d00..3ac52e87320 100644 --- a/src/cascadia/TerminalSettings/TerminalSettings.cpp +++ b/src/cascadia/TerminalSettings/TerminalSettings.cpp @@ -30,6 +30,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation _backgroundImage{}, _backgroundImageOpacity{ 1.0 }, _backgroundImageStretchMode{ winrt::Windows::UI::Xaml::Media::Stretch::UniformToFill }, + _backgroundImageHorizontalAlignment{ winrt::Windows::UI::Xaml::HorizontalAlignment::Center }, + _backgroundImageVerticalAlignment{ winrt::Windows::UI::Xaml::VerticalAlignment::Center }, _keyBindings{ nullptr }, _scrollbarState{ ScrollbarState::Visible } { @@ -236,6 +238,26 @@ namespace winrt::Microsoft::Terminal::Settings::implementation _backgroundImageStretchMode = value; } + winrt::Windows::UI::Xaml::HorizontalAlignment TerminalSettings::BackgroundImageHorizontalAlignment() + { + return _backgroundImageHorizontalAlignment; + } + + void TerminalSettings::BackgroundImageHorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment value) + { + _backgroundImageHorizontalAlignment = value; + } + + winrt::Windows::UI::Xaml::VerticalAlignment TerminalSettings::BackgroundImageVerticalAlignment() + { + return _backgroundImageVerticalAlignment; + } + + void TerminalSettings::BackgroundImageVerticalAlignment(winrt::Windows::UI::Xaml::VerticalAlignment value) + { + _backgroundImageVerticalAlignment = value; + } + Settings::IKeyBindings TerminalSettings::KeyBindings() { return _keyBindings; diff --git a/src/cascadia/TerminalSettings/terminalsettings.h b/src/cascadia/TerminalSettings/terminalsettings.h index 3f2196536e2..39894c6674f 100644 --- a/src/cascadia/TerminalSettings/terminalsettings.h +++ b/src/cascadia/TerminalSettings/terminalsettings.h @@ -69,6 +69,10 @@ namespace winrt::Microsoft::Terminal::Settings::implementation void BackgroundImageOpacity(double value); winrt::Windows::UI::Xaml::Media::Stretch BackgroundImageStretchMode(); void BackgroundImageStretchMode(winrt::Windows::UI::Xaml::Media::Stretch value); + winrt::Windows::UI::Xaml::HorizontalAlignment BackgroundImageHorizontalAlignment(); + void BackgroundImageHorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment value); + winrt::Windows::UI::Xaml::VerticalAlignment BackgroundImageVerticalAlignment(); + void BackgroundImageVerticalAlignment(winrt::Windows::UI::Xaml::VerticalAlignment value); winrt::Microsoft::Terminal::Settings::IKeyBindings KeyBindings(); void KeyBindings(winrt::Microsoft::Terminal::Settings::IKeyBindings const& value); @@ -107,6 +111,8 @@ namespace winrt::Microsoft::Terminal::Settings::implementation hstring _backgroundImage; double _backgroundImageOpacity; winrt::Windows::UI::Xaml::Media::Stretch _backgroundImageStretchMode; + winrt::Windows::UI::Xaml::HorizontalAlignment _backgroundImageHorizontalAlignment; + winrt::Windows::UI::Xaml::VerticalAlignment _backgroundImageVerticalAlignment; hstring _commandline; hstring _startingDir; hstring _envVars; From 0889fc316bddad638ef5427db2f87f22113adb03 Mon Sep 17 00:00:00 2001 From: Robert Jordan Date: Sat, 13 Jul 2019 13:50:05 -0400 Subject: [PATCH 2/5] Implement background image alignment profile setting Implement background image alignment as one profile setting. * This has the benefit of acting as a single setting when the user would likely want to change both horizontal and vertical alignment. * HorizontalAlignment and VerticalAlignment are still stored as a tuple in Profile because they are an optional field. And thus, it would not make sense for one of the alignments to be left unused while the other is not. * Cons are that the tuple signature is quite long, but it is only used in a small number of locations. The Serialize method is also a little mishapen with the nested switch statements. Empty lines have been added between base-level cases to improve readability. --- src/cascadia/TerminalApp/Profile.cpp | 140 ++++++++++++++++++++++++++- src/cascadia/TerminalApp/Profile.h | 3 + 2 files changed, 142 insertions(+), 1 deletion(-) diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index 4c4f9f63869..e445f195b61 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -41,6 +41,7 @@ static constexpr std::string_view IconKey{ "icon" }; static constexpr std::string_view BackgroundImageKey{ "backgroundImage" }; static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" }; static constexpr std::string_view BackgroundimageStretchModeKey{ "backgroundImageStretchMode" }; +static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageAlignment" }; // Possible values for Scrollbar state static constexpr std::wstring_view AlwaysVisible{ L"visible" }; @@ -59,6 +60,17 @@ static constexpr std::string_view ImageStretchModeFill{ "fill" }; static constexpr std::string_view ImageStretchModeUniform{ "uniform" }; static constexpr std::string_view ImageStretchModeUniformTofill{ "uniformToFill" }; +// Possible values for Image Alignment +static constexpr std::string_view ImageAlignmentCenter{ "center" }; +static constexpr std::string_view ImageAlignmentLeft{ "left" }; +static constexpr std::string_view ImageAlignmentTop{ "top" }; +static constexpr std::string_view ImageAlignmentRight{ "right" }; +static constexpr std::string_view ImageAlignmentBottom{ "bottom" }; +static constexpr std::string_view ImageAlignmentTopLeft{ "topLeft" }; +static constexpr std::string_view ImageAlignmentTopRight{ "topRight" }; +static constexpr std::string_view ImageAlignmentBottomLeft{ "bottomLeft" }; +static constexpr std::string_view ImageAlignmentBottomRight{ "bottomRight" }; + Profile::Profile() : Profile(Utils::CreateGuid()) { @@ -91,7 +103,8 @@ Profile::Profile(const winrt::guid& guid) : _icon{}, _backgroundImage{}, _backgroundImageOpacity{}, - _backgroundImageStretchMode{} + _backgroundImageStretchMode{}, + _backgroundImageAlignment{} { } @@ -202,6 +215,14 @@ TerminalSettings Profile::CreateTerminalSettings(const std::vector& terminalSettings.BackgroundImageStretchMode(_backgroundImageStretchMode.value()); } + if (_backgroundImageAlignment) + { + const auto imageHorizontalAlignment = std::get(_backgroundImageAlignment.value()); + const auto imageVerticalAlignment = std::get(_backgroundImageAlignment.value()); + terminalSettings.BackgroundImageHorizontalAlignment(imageHorizontalAlignment); + terminalSettings.BackgroundImageVerticalAlignment(imageVerticalAlignment); + } + return terminalSettings; } @@ -298,6 +319,11 @@ Json::Value Profile::ToJson() const root[JsonKey(BackgroundimageStretchModeKey)] = SerializeImageStretchMode(_backgroundImageStretchMode.value()).data(); } + if (_backgroundImageAlignment) + { + root[JsonKey(BackgroundImageAlignmentKey)] = SerializeImageAlignment(_backgroundImageAlignment.value()).data(); + } + return root; } @@ -434,6 +460,10 @@ Profile Profile::FromJson(const Json::Value& json) { result._backgroundImageStretchMode = ParseImageStretchMode(backgroundImageStretchMode.asString()); } + if (auto backgroundImageAlignment{ json[JsonKey(BackgroundImageAlignmentKey)] }) + { + result._backgroundImageAlignment = ParseImageAlignment(backgroundImageAlignment.asString()); + } return result; } @@ -656,6 +686,114 @@ std::string_view Profile::SerializeImageStretchMode(const winrt::Windows::UI::Xa } } +// Method Description: +// - Helper function for converting a user-specified image horizontal and vertical +// alignment to the appropriate enum values tuple +// Arguments: +// - The value from the profiles.json file +// Return Value: +// - The corresponding enum values tuple which maps to the string provided by the user +std::tuple Profile::ParseImageAlignment(const std::string_view imageAlignment) +{ + if (imageAlignment == ImageAlignmentTopLeft) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Left, + winrt::Windows::UI::Xaml::VerticalAlignment::Top); + } + else if (imageAlignment == ImageAlignmentBottomLeft) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Left, + winrt::Windows::UI::Xaml::VerticalAlignment::Bottom); + } + else if (imageAlignment == ImageAlignmentLeft) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Left, + winrt::Windows::UI::Xaml::VerticalAlignment::Center); + } + else if (imageAlignment == ImageAlignmentTopRight) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Right, + winrt::Windows::UI::Xaml::VerticalAlignment::Top); + } + else if (imageAlignment == ImageAlignmentBottomRight) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Right, + winrt::Windows::UI::Xaml::VerticalAlignment::Bottom); + } + else if (imageAlignment == ImageAlignmentRight) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Right, + winrt::Windows::UI::Xaml::VerticalAlignment::Center); + } + else if (imageAlignment == ImageAlignmentTop) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Center, + winrt::Windows::UI::Xaml::VerticalAlignment::Top); + } + else if (imageAlignment == ImageAlignmentBottom) + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Center, + winrt::Windows::UI::Xaml::VerticalAlignment::Bottom); + } + else // Fall through to default alignment + { + return std::make_tuple(winrt::Windows::UI::Xaml::HorizontalAlignment::Center, + winrt::Windows::UI::Xaml::VerticalAlignment::Center); + } +} + +// Method Description: +// - Helper function for converting the HorizontalAlignment+VerticalAlignment tuple +// to the correct string value. +// Arguments: +// - imageAlignment: The enum values tuple to convert to a string. +// Return Value: +// - The string value for the given ImageAlignment +std::string_view Profile::SerializeImageAlignment(const std::tuple imageAlignment) +{ + const auto imageHorizontalAlignment = std::get(imageAlignment); + const auto imageVerticalAlignment = std::get(imageAlignment); + switch (imageHorizontalAlignment) + { + case winrt::Windows::UI::Xaml::HorizontalAlignment::Left: + switch (imageVerticalAlignment) + { + case winrt::Windows::UI::Xaml::VerticalAlignment::Top: + return ImageAlignmentTopLeft; + case winrt::Windows::UI::Xaml::VerticalAlignment::Bottom: + return ImageAlignmentBottomLeft; + default: + case winrt::Windows::UI::Xaml::VerticalAlignment::Center: + return ImageAlignmentLeft; + } + + case winrt::Windows::UI::Xaml::HorizontalAlignment::Right: + switch (imageVerticalAlignment) + { + case winrt::Windows::UI::Xaml::VerticalAlignment::Top: + return ImageAlignmentTopRight; + case winrt::Windows::UI::Xaml::VerticalAlignment::Bottom: + return ImageAlignmentBottomRight; + default: + case winrt::Windows::UI::Xaml::VerticalAlignment::Center: + return ImageAlignmentRight; + } + + default: + case winrt::Windows::UI::Xaml::HorizontalAlignment::Center: + switch (imageVerticalAlignment) + { + case winrt::Windows::UI::Xaml::VerticalAlignment::Top: + return ImageAlignmentTop; + case winrt::Windows::UI::Xaml::VerticalAlignment::Bottom: + return ImageAlignmentBottom; + default: + case winrt::Windows::UI::Xaml::VerticalAlignment::Center: + return ImageAlignmentCenter; + } + } +} + // Method Description: // - Helper function for converting a user-specified cursor style corresponding // CursorStyle enum value diff --git a/src/cascadia/TerminalApp/Profile.h b/src/cascadia/TerminalApp/Profile.h index 9cfc3330c3b..10fc724ab9b 100644 --- a/src/cascadia/TerminalApp/Profile.h +++ b/src/cascadia/TerminalApp/Profile.h @@ -62,6 +62,8 @@ class TerminalApp::Profile final static winrt::Microsoft::Terminal::Settings::ScrollbarState ParseScrollbarState(const std::wstring& scrollbarState); static winrt::Windows::UI::Xaml::Media::Stretch ParseImageStretchMode(const std::string_view imageStretchMode); static std::string_view SerializeImageStretchMode(const winrt::Windows::UI::Xaml::Media::Stretch imageStretchMode); + static std::tuple ParseImageAlignment(const std::string_view imageAlignment); + static std::string_view SerializeImageAlignment(const std::tuple imageAlignment); static winrt::Microsoft::Terminal::Settings::CursorStyle _ParseCursorShape(const std::wstring& cursorShapeString); static std::wstring_view _SerializeCursorStyle(const winrt::Microsoft::Terminal::Settings::CursorStyle cursorShape); @@ -91,6 +93,7 @@ class TerminalApp::Profile final std::optional _backgroundImage; std::optional _backgroundImageOpacity; std::optional _backgroundImageStretchMode; + std::optional> _backgroundImageAlignment; std::optional _scrollbarState; bool _closeOnExit; From f48961c490aee7c1260e10fd50e5521125474be0 Mon Sep 17 00:00:00 2001 From: Robert Jordan Date: Sat, 13 Jul 2019 14:55:34 -0400 Subject: [PATCH 3/5] Fix capitalization typo for BackgroundImageStretchModeKey In Profiles.cpp, the key for the image stretch mode json property had a lowercase 'i' in "Backgroundimage", not following proper UpperCamelCase. The "i" has been capitalized and the two usages of the constant have been updated as well. --- src/cascadia/TerminalApp/Profile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cascadia/TerminalApp/Profile.cpp b/src/cascadia/TerminalApp/Profile.cpp index e445f195b61..f9551842285 100644 --- a/src/cascadia/TerminalApp/Profile.cpp +++ b/src/cascadia/TerminalApp/Profile.cpp @@ -40,7 +40,7 @@ static constexpr std::string_view StartingDirectoryKey{ "startingDirectory" }; static constexpr std::string_view IconKey{ "icon" }; static constexpr std::string_view BackgroundImageKey{ "backgroundImage" }; static constexpr std::string_view BackgroundImageOpacityKey{ "backgroundImageOpacity" }; -static constexpr std::string_view BackgroundimageStretchModeKey{ "backgroundImageStretchMode" }; +static constexpr std::string_view BackgroundImageStretchModeKey{ "backgroundImageStretchMode" }; static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageAlignment" }; // Possible values for Scrollbar state @@ -316,7 +316,7 @@ Json::Value Profile::ToJson() const if (_backgroundImageStretchMode) { - root[JsonKey(BackgroundimageStretchModeKey)] = SerializeImageStretchMode(_backgroundImageStretchMode.value()).data(); + root[JsonKey(BackgroundImageStretchModeKey)] = SerializeImageStretchMode(_backgroundImageStretchMode.value()).data(); } if (_backgroundImageAlignment) @@ -456,7 +456,7 @@ Profile Profile::FromJson(const Json::Value& json) { result._backgroundImageOpacity = backgroundImageOpacity.asFloat(); } - if (auto backgroundImageStretchMode{ json[JsonKey(BackgroundimageStretchModeKey)] }) + if (auto backgroundImageStretchMode{ json[JsonKey(BackgroundImageStretchModeKey)] }) { result._backgroundImageStretchMode = ParseImageStretchMode(backgroundImageStretchMode.asString()); } From 28cec5cdeb3527ba4d3a7c585448c6877548492b Mon Sep 17 00:00:00 2001 From: Robert Jordan Date: Tue, 16 Jul 2019 13:32:01 -0400 Subject: [PATCH 4/5] Document Background Image settings * Adds entries SettingsSchema.md for the original 3 backgroundImage settings in addition to the new backgroundImageAlignment setting. --- doc/cascadia/SettingsSchema.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/cascadia/SettingsSchema.md b/doc/cascadia/SettingsSchema.md index e1f6c14fdcd..c865d4b8b70 100644 --- a/doc/cascadia/SettingsSchema.md +++ b/doc/cascadia/SettingsSchema.md @@ -35,6 +35,10 @@ Properties listed below are specific to each unique profile. | `startingDirectory` | _Required_ | String | `%USERPROFILE%` | The directory the shell starts in when it is loaded. | | `useAcrylic` | _Required_ | Boolean | `false` | When set to `true`, the window will have an acrylic background. When set to `false`, the window will have a plain, untextured background. | | `background` | Optional | String | | Sets the background color of the profile. Overrides `background` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. | +| `backgroundImage` | Optional | String | | Sets the file location of the Image to draw over the window background. | +| `backgroundImageAlignment` | Optional | String | `center` | Sets how the background image aligns to the boundaries of the window. Possible values: `"center"`, `"left"`, `"top"`, `"right"`, `"bottom"`, `"topLeft"`, `"topRight"`, `"bottomLeft"`, `"bottomRight"` | +| `backgroundImageOpacity` | Optional | Number | `1.0` | Sets the transparency of the background image. Accepts floating point values from 0-1. | +| `backgroundImageStretchMode` | Optional | String | `uniformToFill` | Sets how the background image is resized to fill the window. Possible values: `"none"`, `"fill"`, `"uniform"`, `"uniformToFill"` | | `colorTable` | Optional | Array[String] | | Array of colors used in the profile if `colorscheme` is not set. Colors use hex color format: `"#rrggbb"`. Ordering is as follows: `[black, red, green, yellow, blue, magenta, cyan, white, bright black, bright red, bright green, bright yellow, bright blue, bright magenta, bright cyan, bright white]` | | `cursorHeight` | Optional | Integer | | Sets the percentage height of the cursor starting from the bottom. Only works when `cursorShape` is set to `"vintage"`. Accepts values from 25-100. | | `foreground` | Optional | String | | Sets the foreground color of the profile. Overrides `foreground` set in color scheme if `colorscheme` is set. Uses hex color format: `"#rrggbb"`. | From 7f0ee15a9fd96ed0f272c9b9a5858edd69fbcf13 Mon Sep 17 00:00:00 2001 From: Robert Jordan Date: Tue, 16 Jul 2019 13:35:04 -0400 Subject: [PATCH 5/5] Fix setting capitalization error in UsingJsonSettings.md * The background image example in UsingJsonSettings.md listing a backgroundImageStretchMode of "Fill" has been corrected to "fill". --- doc/user-docs/UsingJsonSettings.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user-docs/UsingJsonSettings.md b/doc/user-docs/UsingJsonSettings.md index a616d5c5ab7..e8d680f7f2c 100644 --- a/doc/user-docs/UsingJsonSettings.md +++ b/doc/user-docs/UsingJsonSettings.md @@ -110,7 +110,7 @@ The schema name can then be referenced in one or more profiles. ```json "backgroundImage": "ms-appdata:///Roaming/openlogo.jpg", "backgroundImageOpacity": 0.3, - "backgroundImageStretchMode": "Fill", + "backgroundImageStretchMode": "fill", ``` 5. Make sure that `useAcrylic` is `false`. 6. Save the file.