Enable Vintage Opacity (#11180)

## Summary of the Pull Request
![603-final](https://user-images.githubusercontent.com/18356694/132585665-afed3210-257a-4fee-9b43-4273a0f5cf69.gif)

Adds support for vintage style opacity, on Windows 11+. The API we're using for this exists since the time immemorial, but there's a bug in XAML Islands that prevents it from working right until Windows 11 (which we're working on backporting).

Replaces the `acrylicOpacity` setting with `opacity`, which is a uint between 0 and 100 (inclusive), default to 100.

`useAcrylic` now controls whether acrylic is used or not. Setting an opacity < 100 with `"useAcrylic": false` will use vintage style opacity.

Mouse wheeling adjusts opacity. Whether acrylic is used or not is dependent upon `useAcrylic`.

`opacity` will stealthily default to 50 if `useAcrylic:true` is set.

## PR Checklist
* [x] Closes #603
* [x] I work here
* [x] Tests added/passed
* [x] https://github.com/MicrosoftDocs/terminal/pull/416

## Detailed Description of the Pull Request / Additional comments

Opacity was moved to AppearanceConfig. In the future, I have a mind to allow unfocused acrylic, so that'll be important then. 

## Validation Steps Performed
_just look at it_
This commit is contained in:
Mike Griese 2021-09-20 12:08:13 -05:00 committed by GitHub
parent 0a7310dee4
commit 74f11b8203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 205 additions and 115 deletions

View File

@ -1401,7 +1401,8 @@
"properties": {
"acrylicOpacity": {
"default": 0.5,
"description": "When useAcrylic is set to true, it sets the transparency of the window for the profile. Accepts floating point values from 0-1 (default 0.5).",
"description": "[deprecated] Please use `opacity` instead.",
"deprecated": true,
"maximum": 1,
"minimum": 0,
"type": "number"
@ -1614,6 +1615,13 @@
"minLength": 1,
"type": "string"
},
"opacity": {
"default": 100,
"description": "Sets the opacity of the window for the profile. Accepts values from 0-100. Defaults to 50 when useAcrylic is set to true.",
"maximum": 100,
"minimum": 0,
"type": "number"
},
"padding": {
"default": "8, 8, 8, 8",
"description": "Sets the padding around the text within the window. Can have three different formats:\n -\"#\" sets the same padding for all sides \n -\"#, #\" sets the same padding for left-right and top-bottom\n -\"#, #, #, #\" sets the padding individually for left, top, right, and bottom.",

View File

@ -45,7 +45,7 @@ namespace winrt::SampleApp::implementation
WINRT_PROPERTY(winrt::hstring, ProfileName);
WINRT_PROPERTY(bool, UseAcrylic, false);
WINRT_PROPERTY(double, TintOpacity, 0.5);
WINRT_PROPERTY(double, Opacity, .5);
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas");
WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE);

View File

@ -53,10 +53,6 @@ Pane::Pane(const Profile& profile, const TermControl& control, const bool lastFo
_SetupResources();
}
// Use the unfocused border color as the pane background, so an actual color
// appears behind panes as we animate them sliding in.
_root.Background(s_unfocusedBorderBrush);
// Register an event with the control to have it inform us when it gains focus.
_gotFocusRevoker = _control.GotFocus(winrt::auto_revoke, { this, &Pane::_ControlGotFocusHandler });
_lostFocusRevoker = _control.LostFocus(winrt::auto_revoke, { this, &Pane::_ControlLostFocusHandler });
@ -1616,6 +1612,8 @@ winrt::fire_and_forget Pane::_CloseChildRoutine(const bool closeFirst)
// Create the dummy grid. This grid will be the one we actually animate,
// in the place of the closed pane.
Controls::Grid dummyGrid;
// GH#603 - we can safely add a BG here, as the control is gone right
// away, to fill the space as the rest of the pane expands.
dummyGrid.Background(s_unfocusedBorderBrush);
// It should be the size of the closed pane.
dummyGrid.Width(removedOriginalSize.Width);
@ -1871,6 +1869,19 @@ void Pane::_SetupEntranceAnimation()
return;
}
// Use the unfocused border color as the pane background, so an actual color
// appears behind panes as we animate them sliding in.
//
// GH#603 - We set only the background of the new pane, while it animates
// in. Once the animation is done, we'll remove that background, so if the
// user wants vintage opacity, they'll be able to see what's under the
// window.
// * If we don't give it a background, then the BG will be entirely transparent.
// * If we give the parent (us) root BG a color, then a transparent pane
// will flash opaque during the animation, then back to transparent, which
// looks bad.
_secondChild->_root.Background(s_unfocusedBorderBrush);
const auto [firstSize, secondSize] = _CalcChildrenSizes(::base::saturated_cast<float>(totalSize));
// This is safe to capture this, because it's only being called in the
@ -1938,11 +1949,12 @@ void Pane::_SetupEntranceAnimation()
// When the animation is completed, undo the trickiness from before, to
// restore the controls to the behavior they'd usually have.
animation.Completed([childGrid, control](auto&&, auto&&) {
animation.Completed([childGrid, control, root = _secondChild->_root](auto&&, auto&&) {
control.Width(NAN);
childGrid.Width(NAN);
childGrid.HorizontalAlignment(HorizontalAlignment::Stretch);
control.HorizontalAlignment(HorizontalAlignment::Stretch);
root.Background(nullptr);
});
}
else
@ -1956,11 +1968,12 @@ void Pane::_SetupEntranceAnimation()
// When the animation is completed, undo the trickiness from before, to
// restore the controls to the behavior they'd usually have.
animation.Completed([childGrid, control](auto&&, auto&&) {
animation.Completed([childGrid, control, root = _secondChild->_root](auto&&, auto&&) {
control.Height(NAN);
childGrid.Height(NAN);
childGrid.VerticalAlignment(VerticalAlignment::Stretch);
control.VerticalAlignment(VerticalAlignment::Stretch);
root.Background(nullptr);
});
}

View File

@ -87,7 +87,7 @@ namespace winrt::TerminalApp::implementation
TraceLoggingBool(usedManualProfile, "ProfileSpecified", "Whether the new tab specified a profile explicitly"),
TraceLoggingGuid(profile.Guid(), "ProfileGuid", "The GUID of the profile spawned in the new tab"),
TraceLoggingBool(settings.DefaultSettings().UseAcrylic(), "UseAcrylic", "The acrylic preference from the settings"),
TraceLoggingFloat64(settings.DefaultSettings().TintOpacity(), "TintOpacity", "Opacity preference from the settings"),
TraceLoggingFloat64(settings.DefaultSettings().Opacity(), "TintOpacity", "Opacity preference from the settings"),
TraceLoggingWideString(settings.DefaultSettings().FontFace().c_str(), "FontFace", "Font face chosen in the settings"),
TraceLoggingWideString(schemeName.data(), "SchemeName", "Color scheme set in the settings"),
TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES),

View File

@ -9,10 +9,11 @@
xmlns:local="using:TerminalApp"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mux="using:Microsoft.UI.Xaml.Controls"
Background="Transparent"
mc:Ignorable="d">
<Grid x:Name="Root"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />

View File

@ -276,7 +276,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// GH#5098: Inform the engine of the opacity of the default text background.
if (_settings.UseAcrylic())
{
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.TintOpacity()));
_renderEngine->SetDefaultTextBackgroundOpacity(::base::saturated_cast<float>(_settings.Opacity()));
}
THROW_IF_FAILED(_renderEngine->Enable());
@ -425,41 +425,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return;
}
auto newOpacity = std::clamp(_settings.TintOpacity() + adjustment,
auto newOpacity = std::clamp(_settings.Opacity() + adjustment,
0.0,
1.0);
if (_settings.UseAcrylic())
{
try
{
_settings.TintOpacity(newOpacity);
if (newOpacity >= 1.0)
{
_settings.UseAcrylic(false);
}
else
{
// GH#5098: Inform the engine of the new opacity of the default text background.
SetBackgroundOpacity(::base::saturated_cast<float>(newOpacity));
}
// GH#5098: Inform the engine of the new opacity of the default text background.
SetBackgroundOpacity(::base::saturated_cast<float>(newOpacity));
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
_TransparencyChangedHandlers(*this, *eventArgs);
}
CATCH_LOG();
}
else if (adjustment < 0)
{
_settings.UseAcrylic(true);
_settings.Opacity(newOpacity);
//Setting initial opacity set to 1 to ensure smooth transition to acrylic during mouse scroll
newOpacity = std::clamp(1.0 + adjustment, 0.0, 1.0);
_settings.TintOpacity(newOpacity);
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
_TransparencyChangedHandlers(*this, *eventArgs);
}
auto eventArgs = winrt::make_self<TransparencyChangedEventArgs>(newOpacity);
_TransparencyChangedHandlers(*this, *eventArgs);
}
void ControlCore::ToggleShaderEffects()

View File

@ -13,6 +13,7 @@ namespace Microsoft.Terminal.Control
Windows.UI.Xaml.VerticalAlignment BackgroundImageVerticalAlignment;
Boolean IntenseIsBold;
// IntenseIsBright is in Core Appearance
Double Opacity;
// Experimental settings
Boolean RetroTerminalEffect;

View File

@ -29,7 +29,6 @@ namespace Microsoft.Terminal.Control
String ProfileName;
Boolean UseAcrylic;
Double TintOpacity;
ScrollbarState ScrollState;
String FontFace;

View File

@ -428,6 +428,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// - <none>
void TermControl::_InitializeBackgroundBrush()
{
auto appearance = _settings.try_as<IControlAppearance>();
if (_settings.UseAcrylic())
{
// See if we've already got an acrylic background brush
@ -449,7 +450,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation
acrylic.TintColor(bgColor);
// Apply brush settings
acrylic.TintOpacity(_settings.TintOpacity());
acrylic.TintOpacity(appearance.Opacity());
// Apply brush to control if it's not already there
if (RootGrid().Background() != acrylic)
@ -458,15 +459,16 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
// GH#5098: Inform the engine of the new opacity of the default text background.
_core.SetBackgroundOpacity(::base::saturated_cast<float>(_settings.TintOpacity()));
_core.SetBackgroundOpacity(::base::saturated_cast<float>(appearance.Opacity()));
}
else
{
Media::SolidColorBrush solidColor{};
solidColor.Opacity(_settings.Opacity());
RootGrid().Background(solidColor);
// GH#5098: Inform the engine of the new opacity of the default text background.
_core.SetBackgroundOpacity(1.0f);
_core.SetBackgroundOpacity(appearance.Opacity());
}
}
@ -497,7 +499,9 @@ namespace winrt::Microsoft::Terminal::Control::implementation
}
else if (auto solidColor = RootGrid().Background().try_as<Media::SolidColorBrush>())
{
const auto originalOpacity = solidColor.Opacity();
solidColor.Color(bg);
solidColor.Opacity(originalOpacity);
}
}
}

View File

@ -14,6 +14,7 @@
d:DesignWidth="1024"
AllowDrop="True"
AllowFocusOnInteraction="True"
Background="Transparent"
CharacterReceived="_CharacterHandler"
DragOver="_DragOverHandler"
Drop="_DragDropHandler"

View File

@ -8,6 +8,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Page.Resources>

View File

@ -22,7 +22,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void SetAcrylicOpacityPercentageValue(double value)
{
AcrylicOpacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
_profile.DefaultAppearance().Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value));
};
void SetPadding(double value)
@ -66,7 +66,6 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile, TabColor);
OBSERVABLE_PROJECTED_SETTING(_profile, SuppressApplicationTitle);
OBSERVABLE_PROJECTED_SETTING(_profile, UseAcrylic);
OBSERVABLE_PROJECTED_SETTING(_profile, AcrylicOpacity);
OBSERVABLE_PROJECTED_SETTING(_profile, ScrollState);
OBSERVABLE_PROJECTED_SETTING(_profile, Padding);
OBSERVABLE_PROJECTED_SETTING(_profile, Commandline);
@ -78,6 +77,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Background);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), SelectionBackground);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), CursorColor);
OBSERVABLE_PROJECTED_SETTING(_profile.DefaultAppearance(), Opacity);
OBSERVABLE_PROJECTED_SETTING(_profile, HistorySize);
OBSERVABLE_PROJECTED_SETTING(_profile, SnapOnInput);
OBSERVABLE_PROJECTED_SETTING(_profile, AltGrAliasing);

View File

@ -47,7 +47,7 @@ namespace Microsoft.Terminal.Settings.Editor
OBSERVABLE_PROJECTED_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, TabColor);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, SuppressApplicationTitle);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Boolean, UseAcrylic);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, AcrylicOpacity);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Double, Opacity);
OBSERVABLE_PROJECTED_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState);
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Padding);
OBSERVABLE_PROJECTED_PROFILE_SETTING(String, Commandline);
@ -109,6 +109,6 @@ namespace Microsoft.Terminal.Settings.Editor
IInspectable CurrentScrollState;
Windows.Foundation.Collections.IObservableVector<Microsoft.Terminal.Settings.Editor.EnumEntry> ScrollStateList { get; };
Windows.UI.Xaml.Controls.Slider AcrylicOpacitySlider { get; };
Windows.UI.Xaml.Controls.Slider OpacitySlider { get; };
}
}

View File

@ -238,11 +238,33 @@
<local:Appearances Appearance="{x:Bind State.Profile.DefaultAppearance, Mode=OneWay}"
SourceProfile="{x:Bind State.Profile, Mode=OneWay}" />
<!-- Grouping: Acrylic -->
<!-- Grouping: Transparency -->
<StackPanel Style="{StaticResource PivotStackStyle}">
<TextBlock x:Uid="Profile_AcrylicHeader"
<TextBlock x:Uid="Profile_TransparencyHeader"
Style="{StaticResource SubtitleTextBlockStyle}" />
<!-- Opacity -->
<local:SettingContainer x:Name="OpacityContainer"
x:Uid="Profile_Opacity"
ClearSettingValue="{x:Bind State.Profile.ClearOpacity}"
HasSettingValue="{x:Bind State.Profile.HasOpacity, Mode=OneWay}"
SettingOverrideSource="{x:Bind State.Profile.OpacityOverrideSource, Mode=OneWay}">
<StackPanel x:Name="OpacityControl">
<Grid Style="{StaticResource CustomSliderControlGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Slider x:Name="OpacitySlider"
Grid.Column="0"
Value="{x:Bind local:Converters.PercentageToPercentageValue(State.Profile.Opacity), BindBack=State.Profile.SetAcrylicOpacityPercentageValue, Mode=TwoWay}" />
<TextBlock Grid.Column="1"
Style="{StaticResource SliderValueLabelStyle}"
Text="{x:Bind local:Converters.AppendPercentageSign(OpacitySlider.Value), Mode=OneWay}" />
</Grid>
</StackPanel>
</local:SettingContainer>
<!-- Use Acrylic -->
<local:SettingContainer x:Uid="Profile_UseAcrylic"
Margin="0"
@ -253,28 +275,6 @@
IsOn="{x:Bind State.Profile.UseAcrylic, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Acrylic Opacity -->
<local:SettingContainer x:Name="AcrylicOpacityContainer"
x:Uid="Profile_AcrylicOpacity"
ClearSettingValue="{x:Bind State.Profile.ClearAcrylicOpacity}"
HasSettingValue="{x:Bind State.Profile.HasAcrylicOpacity, Mode=OneWay}"
SettingOverrideSource="{x:Bind State.Profile.AcrylicOpacityOverrideSource, Mode=OneWay}"
Visibility="{Binding ElementName=UseAcrylicToggleSwitch, Path=IsOn, Mode=OneWay}">
<StackPanel x:Name="AcrylicOpacityControl">
<Grid Style="{StaticResource CustomSliderControlGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Slider x:Name="AcrylicOpacitySlider"
Grid.Column="0"
Value="{x:Bind local:Converters.PercentageToPercentageValue(State.Profile.AcrylicOpacity), BindBack=State.Profile.SetAcrylicOpacityPercentageValue, Mode=TwoWay}" />
<TextBlock Grid.Column="1"
Style="{StaticResource SliderValueLabelStyle}"
Text="{x:Bind local:Converters.AppendPercentageSign(AcrylicOpacitySlider.Value), Mode=OneWay}" />
</Grid>
</StackPanel>
</local:SettingContainer>
</StackPanel>
<!-- Grouping: Window -->

View File

@ -495,6 +495,14 @@
<value>Sets the transparency of the window.</value>
<comment>A description for what the "acrylic opacity" setting does. Presented near "Profile_AcrylicOpacity.Header".</comment>
</data>
<data name="Profile_Opacity.Header" xml:space="preserve">
<value>Background Opacity</value>
<comment>Header for a control to determine the level of opacity for the background of the control. The user can choose to make the background of the app more or less opaque.</comment>
</data>
<data name="Profile_Opacity.HelpText" xml:space="preserve">
<value>Sets the transparency of the window.</value>
<comment>A description for what the "opacity" setting does. Presented near "Profile_Opacity.Header".</comment>
</data>
<data name="Profile_Advanced.Header" xml:space="preserve">
<value>Advanced</value>
<comment>Header for a sub-page of profile settings focused on more advanced scenarios.</comment>
@ -986,6 +994,10 @@
<value>Acrylic</value>
<comment>Header for a group of settings related to the acrylic texture rendering on the background of the app.</comment>
</data>
<data name="Profile_TransparencyHeader.Text" xml:space="preserve">
<value>Transparency</value>
<comment>Header for a group of settings related to transparency, including the acrylic texture rendering on the background of the app.</comment>
</data>
<data name="Profile_BackgroundHeader.Text" xml:space="preserve">
<value>Background image</value>
<comment>Header for a group of settings that control the image presented on the background of the app. Presented near "Profile_BackgroundImage" and other keys starting with "Profile_BackgroundImage".</comment>

View File

@ -26,6 +26,8 @@ static constexpr std::string_view BackgroundImageAlignmentKey{ "backgroundImageA
static constexpr std::string_view RetroTerminalEffectKey{ "experimental.retroTerminalEffect" };
static constexpr std::string_view PixelShaderPathKey{ "experimental.pixelShaderPath" };
static constexpr std::string_view IntenseTextStyleKey{ "intenseTextStyle" };
static constexpr std::string_view LegacyAcrylicTransparencyKey{ "acrylicOpacity" };
static constexpr std::string_view OpacityKey{ "opacity" };
winrt::Microsoft::Terminal::Settings::Model::implementation::AppearanceConfig::AppearanceConfig(const winrt::weak_ref<Profile> sourceProfile) :
_sourceProfile(sourceProfile)
@ -50,6 +52,7 @@ winrt::com_ptr<AppearanceConfig> AppearanceConfig::CopyAppearance(const winrt::c
appearance->_RetroTerminalEffect = sourceAppearance->_RetroTerminalEffect;
appearance->_PixelShaderPath = sourceAppearance->_PixelShaderPath;
appearance->_IntenseTextStyle = sourceAppearance->_IntenseTextStyle;
appearance->_Opacity = sourceAppearance->_Opacity;
return appearance;
}
@ -71,6 +74,7 @@ Json::Value AppearanceConfig::ToJson() const
JsonUtils::SetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
JsonUtils::SetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
JsonUtils::SetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
JsonUtils::SetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
return json;
}
@ -102,6 +106,8 @@ void AppearanceConfig::LayerJson(const Json::Value& json)
JsonUtils::GetValueForKey(json, RetroTerminalEffectKey, _RetroTerminalEffect);
JsonUtils::GetValueForKey(json, PixelShaderPathKey, _PixelShaderPath);
JsonUtils::GetValueForKey(json, IntenseTextStyleKey, _IntenseTextStyle);
JsonUtils::GetValueForKey(json, LegacyAcrylicTransparencyKey, _Opacity);
JsonUtils::GetValueForKey(json, OpacityKey, _Opacity, JsonUtils::OptionalConverter<double, IntAsFloatPercentConversionTrait>{});
}
winrt::Microsoft::Terminal::Settings::Model::Profile AppearanceConfig::SourceProfile()

View File

@ -53,6 +53,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::IAppearanceConfig, bool, RetroTerminalEffect, false);
INHERITABLE_SETTING(Model::IAppearanceConfig, hstring, PixelShaderPath, L"");
INHERITABLE_SETTING(Model::IAppearanceConfig, Model::IntenseStyle, IntenseTextStyle, Model::IntenseStyle::Bright);
INHERITABLE_SETTING(Model::IAppearanceConfig, double, Opacity, 1.0);
private:
winrt::weak_ref<Profile> _sourceProfile;

View File

@ -307,7 +307,6 @@ winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::Duplicate
DUPLICATE_SETTING_MACRO(TabColor);
DUPLICATE_SETTING_MACRO(SuppressApplicationTitle);
DUPLICATE_SETTING_MACRO(UseAcrylic);
DUPLICATE_SETTING_MACRO(AcrylicOpacity);
DUPLICATE_SETTING_MACRO(ScrollState);
DUPLICATE_SETTING_MACRO(Padding);
DUPLICATE_SETTING_MACRO(Commandline);
@ -347,6 +346,7 @@ winrt::Microsoft::Terminal::Settings::Model::Profile CascadiaSettings::Duplicate
DUPLICATE_SETTING_MACRO_SUB(appearance, target, RetroTerminalEffect);
DUPLICATE_SETTING_MACRO_SUB(appearance, target, CursorShape);
DUPLICATE_SETTING_MACRO_SUB(appearance, target, CursorHeight);
DUPLICATE_SETTING_MACRO_SUB(appearance, target, Opacity);
}
// UnfocusedAppearance is treated as a single setting,

View File

@ -51,5 +51,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_APPEARANCE_SETTING(Boolean, RetroTerminalEffect);
INHERITABLE_APPEARANCE_SETTING(String, PixelShaderPath);
INHERITABLE_APPEARANCE_SETTING(IntenseStyle, IntenseTextStyle);
INHERITABLE_APPEARANCE_SETTING(Double, Opacity);
};
}

View File

@ -36,7 +36,6 @@ static constexpr std::string_view AltGrAliasingKey{ "altGrAliasing" };
static constexpr std::string_view ConnectionTypeKey{ "connectionType" };
static constexpr std::string_view CommandlineKey{ "commandline" };
static constexpr std::string_view FontInfoKey{ "font" };
static constexpr std::string_view AcrylicTransparencyKey{ "acrylicOpacity" };
static constexpr std::string_view UseAcrylicKey{ "useAcrylic" };
static constexpr std::string_view ScrollbarStateKey{ "scrollbarState" };
static constexpr std::string_view CloseOnExitKey{ "closeOnExit" };
@ -95,7 +94,6 @@ winrt::com_ptr<Profile> Profile::CopySettings(winrt::com_ptr<Profile> source)
profile->_TabColor = source->_TabColor;
profile->_SuppressApplicationTitle = source->_SuppressApplicationTitle;
profile->_UseAcrylic = source->_UseAcrylic;
profile->_AcrylicOpacity = source->_AcrylicOpacity;
profile->_ScrollState = source->_ScrollState;
profile->_Padding = source->_Padding;
profile->_Commandline = source->_Commandline;
@ -356,7 +354,6 @@ void Profile::LayerJson(const Json::Value& json)
// Control Settings
JsonUtils::GetValueForKey(json, ConnectionTypeKey, _ConnectionType);
JsonUtils::GetValueForKey(json, CommandlineKey, _Commandline);
JsonUtils::GetValueForKey(json, AcrylicTransparencyKey, _AcrylicOpacity);
JsonUtils::GetValueForKey(json, UseAcrylicKey, _UseAcrylic);
JsonUtils::GetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
JsonUtils::GetValueForKey(json, CloseOnExitKey, _CloseOnExit);
@ -548,7 +545,6 @@ Json::Value Profile::ToJson() const
// Control Settings
JsonUtils::SetValueForKey(json, ConnectionTypeKey, _ConnectionType);
JsonUtils::SetValueForKey(json, CommandlineKey, _Commandline);
JsonUtils::SetValueForKey(json, AcrylicTransparencyKey, _AcrylicOpacity);
JsonUtils::SetValueForKey(json, UseAcrylicKey, _UseAcrylic);
JsonUtils::SetValueForKey(json, SuppressApplicationTitleKey, _SuppressApplicationTitle);
JsonUtils::SetValueForKey(json, CloseOnExitKey, _CloseOnExit);

View File

@ -67,7 +67,6 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_PROFILE_SETTING(Windows.Foundation.IReference<Microsoft.Terminal.Core.Color>, TabColor);
INHERITABLE_PROFILE_SETTING(Boolean, SuppressApplicationTitle);
INHERITABLE_PROFILE_SETTING(Boolean, UseAcrylic);
INHERITABLE_PROFILE_SETTING(Double, AcrylicOpacity);
INHERITABLE_PROFILE_SETTING(Microsoft.Terminal.Control.ScrollbarState, ScrollState);
INHERITABLE_PROFILE_SETTING(String, Padding);
INHERITABLE_PROFILE_SETTING(String, Commandline);

View File

@ -201,6 +201,16 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_IntenseIsBold = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bold);
_IntenseIsBright = WI_IsFlagSet(appearance.IntenseTextStyle(), Microsoft::Terminal::Settings::Model::IntenseStyle::Bright);
// If the user set an opacity, then just use that. Otherwise, change the
// default value based off of whether useAcrylic was set or not. If they
// want acrylic, then default to 50%. Otherwise, default to 100% (fully
// opaque)
_Opacity = appearance.HasOpacity() ?
appearance.Opacity() :
UseAcrylic() ?
.5 :
1.0;
}
// Method Description:
@ -273,7 +283,6 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
// Fill in the remaining properties from the profile
_ProfileName = profile.Name();
_UseAcrylic = profile.UseAcrylic();
_TintOpacity = profile.AcrylicOpacity();
_FontFace = profile.FontInfo().FontFace();
_FontSize = profile.FontInfo().FontSize();

View File

@ -118,7 +118,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, hstring, ProfileName);
INHERITABLE_SETTING(Model::TerminalSettings, bool, UseAcrylic, false);
INHERITABLE_SETTING(Model::TerminalSettings, double, TintOpacity, 0.5);
INHERITABLE_SETTING(Model::TerminalSettings, double, Opacity, UseAcrylic() ? 0.5 : 1.0);
INHERITABLE_SETTING(Model::TerminalSettings, hstring, Padding, DEFAULT_PADDING);
INHERITABLE_SETTING(Model::TerminalSettings, hstring, FontFace, DEFAULT_FONT_FACE);
INHERITABLE_SETTING(Model::TerminalSettings, int32_t, FontSize, DEFAULT_FONT_SIZE);

View File

@ -342,6 +342,34 @@ struct ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<::winr
}
};
struct IntAsFloatPercentConversionTrait : ::Microsoft::Terminal::Settings::Model::JsonUtils::ConversionTrait<double>
{
double FromJson(const Json::Value& json)
{
return ::base::saturated_cast<double>(json.asUInt()) / 100.0;
}
bool CanConvert(const Json::Value& json)
{
if (!json.isUInt())
{
return false;
}
const auto value = json.asUInt();
return value >= 0 && value <= 100;
}
Json::Value ToJson(const double& val)
{
return std::clamp(::base::saturated_cast<uint32_t>(std::round(val * 100.0)), 0u, 100u);
}
std::string TypeDescription() const
{
return "number (>= 0, <=100)";
}
};
// Possible FocusDirection values
JSON_ENUM_MAPPER(::winrt::Microsoft::Terminal::Settings::Model::FocusDirection)
{

View File

@ -119,7 +119,7 @@ namespace ControlUnitTests
auto [settings, conn] = _createSettingsAndConnection();
settings->UseAcrylic(true);
settings->TintOpacity(0.5f);
settings->Opacity(0.5f);
auto core = createCore(*settings, *conn);
VERIFY_IS_NOT_NULL(core);
@ -128,16 +128,19 @@ namespace ControlUnitTests
double expectedOpacity = 0.5;
auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable {
VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->TintOpacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.TintOpacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.Opacity());
if (expectedOpacity < 1.0)
{
VERIFY_IS_TRUE(settings->UseAcrylic());
VERIFY_IS_TRUE(core->_settings.UseAcrylic());
}
VERIFY_ARE_EQUAL(expectedOpacity < 1.0, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedOpacity < 1.0, core->_settings.UseAcrylic());
// GH#603: Adjusting opacity shouldn't change whether or not we
// requested acrylic.
VERIFY_IS_TRUE(settings->UseAcrylic());
VERIFY_IS_TRUE(core->_settings.UseAcrylic());
};
core->TransparencyChanged(opacityCallback);
@ -220,7 +223,7 @@ namespace ControlUnitTests
{
auto [settings, conn] = _createSettingsAndConnection();
Log::Comment(L"Create ControlCore object");
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
auto core = createCore(*settings, *conn);
VERIFY_IS_NOT_NULL(core);
_standardInit(core);
@ -259,7 +262,7 @@ namespace ControlUnitTests
{
auto [settings, conn] = _createSettingsAndConnection();
Log::Comment(L"Create ControlCore object");
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
auto core = createCore(*settings, *conn);
VERIFY_IS_NOT_NULL(core);
_standardInit(core);
@ -298,7 +301,7 @@ namespace ControlUnitTests
{
auto [settings, conn] = _createSettingsAndConnection();
Log::Comment(L"Create ControlCore object");
auto core = winrt::make_self<Control::implementation::ControlCore>(*settings, *conn);
auto core = createCore(*settings, *conn);
VERIFY_IS_NOT_NULL(core);
_standardInit(core);

View File

@ -99,10 +99,16 @@ namespace ControlUnitTests
WEX::TestExecution::SetVerifyOutput verifyOutputScope{ WEX::TestExecution::VerifyOutputSettings::LogOnlyFailures };
BEGIN_TEST_METHOD_PROPERTIES()
TEST_METHOD_PROPERTY(L"Data:useAcrylic", L"{true, false}")
END_TEST_METHOD_PROPERTIES()
bool useAcrylic;
VERIFY_SUCCEEDED(TestData::TryGetValue(L"useAcrylic", useAcrylic), L"whether or not we should enable acrylic");
auto [settings, conn] = _createSettingsAndConnection();
settings->UseAcrylic(true);
settings->TintOpacity(0.5f);
settings->UseAcrylic(useAcrylic);
settings->Opacity(0.5f);
auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn);
@ -110,16 +116,11 @@ namespace ControlUnitTests
double expectedOpacity = 0.5;
auto opacityCallback = [&](auto&&, Control::TransparencyChangedEventArgs args) mutable {
VERIFY_ARE_EQUAL(expectedOpacity, args.Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->TintOpacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.TintOpacity());
VERIFY_ARE_EQUAL(expectedOpacity, settings->Opacity());
VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.Opacity());
if (expectedOpacity < 1.0)
{
VERIFY_IS_TRUE(settings->UseAcrylic());
VERIFY_IS_TRUE(core->_settings.UseAcrylic());
}
VERIFY_ARE_EQUAL(expectedOpacity < 1.0, settings->UseAcrylic());
VERIFY_ARE_EQUAL(expectedOpacity < 1.0, core->_settings.UseAcrylic());
VERIFY_ARE_EQUAL(useAcrylic, settings->UseAcrylic());
VERIFY_ARE_EQUAL(useAcrylic, core->_settings.UseAcrylic());
};
core->TransparencyChanged(opacityCallback);
@ -157,7 +158,7 @@ namespace ControlUnitTests
// The mouse location and buttons don't matter here.
interactivity->MouseWheel(modifiers,
30,
-30,
til::point{ 0, 0 },
buttonState);
}

View File

@ -51,7 +51,7 @@ namespace ControlUnitTests
WINRT_PROPERTY(winrt::hstring, ProfileName);
WINRT_PROPERTY(bool, UseAcrylic, false);
WINRT_PROPERTY(double, TintOpacity, 0.5);
WINRT_PROPERTY(double, Opacity, .5);
WINRT_PROPERTY(winrt::hstring, Padding, DEFAULT_PADDING);
WINRT_PROPERTY(winrt::hstring, FontFace, L"Consolas");
WINRT_PROPERTY(int32_t, FontSize, DEFAULT_FONT_SIZE);

View File

@ -7,6 +7,8 @@
#include "resource.h"
#include "icon.h"
#include "NotificationIcon.h"
#include <dwmapi.h>
#include <TerminalThemeHelpers.h>
extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -59,7 +61,14 @@ void IslandWindow::MakeWindow() noexcept
// Create the window with the default size here - During the creation of the
// window, the system will give us a chance to set its size in WM_CREATE.
// WM_CREATE will be handled synchronously, before CreateWindow returns.
WINRT_VERIFY(CreateWindowEx(_alwaysOnTop ? WS_EX_TOPMOST : 0,
//
// We need WS_EX_NOREDIRECTIONBITMAP for vintage style opacity, GH#603
//
// WS_EX_LAYERED acts REAL WEIRD with TerminalTrySetTransparentBackground,
// but it works just fine when the window is in the TOPMOST group. But if
// you enable it always, activating the window will remove our DWM frame
// entirely. Weird.
WINRT_VERIFY(CreateWindowEx(WS_EX_NOREDIRECTIONBITMAP | (_alwaysOnTop ? WS_EX_TOPMOST : 0),
wc.lpszClassName,
L"Windows Terminal",
WS_OVERLAPPEDWINDOW,
@ -311,6 +320,10 @@ void IslandWindow::Initialize()
_taskbar = std::move(taskbar);
}
}
// Enable vintage opacity by removing the XAML emergency backstop, GH#603.
// We don't really care if this failed or not.
TerminalTrySetTransparentBackground(true);
}
void IslandWindow::OnSize(const UINT width, const UINT height)
@ -424,6 +437,7 @@ long IslandWindow::_calculateTotalSize(const bool isWidth, const long clientSize
{
_WindowActivatedHandlers();
}
break;
}
@ -828,7 +842,7 @@ void IslandWindow::SetTaskbarProgress(const size_t state, const size_t progress)
}
// From GdiEngine::s_SetWindowLongWHelper
void _SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept
void SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept
{
// SetWindowLong has strange error handling. On success, it returns the
// previous Window Long value and doesn't modify the Last Error state. To
@ -919,14 +933,14 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled)
// First, modify regular window styles as appropriate
auto windowStyle = _getDesiredWindowStyle();
_SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle);
SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle);
// Now modify extended window styles as appropriate
// When moving to fullscreen, remove the window edge style to avoid an
// ugly border when not focused.
auto exWindowStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen);
_SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
// Resize the window, with SWP_FRAMECHANGED, to trigger user32 to
// recalculate the non/client areas
@ -1064,14 +1078,14 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
// First, modify regular window styles as appropriate
auto windowStyle = _getDesiredWindowStyle();
_SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle);
SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle);
// Now modify extended window styles as appropriate
// When moving to fullscreen, remove the window edge style to avoid an
// ugly border when not focused.
auto exWindowStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen);
_SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
// Only change the window position if changing fullscreen state.
if (fChangingFullscreen)

View File

@ -6,6 +6,8 @@
#include <winrt/TerminalApp.h>
#include "../../cascadia/inc/cppwinrt_utils.h"
void SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept;
class IslandWindow :
public BaseWindow<IslandWindow>
{

View File

@ -685,9 +685,18 @@ SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexc
// - the HRESULT returned by DwmExtendFrameIntoClientArea.
void NonClientIslandWindow::_UpdateFrameMargins() const noexcept
{
MARGINS margins = {};
MARGINS margins = { 0, 0, 0, 0 };
if (_GetTopBorderHeight() != 0)
// GH#603: When we're in Focus Mode, hide the titlebar, by setting it to a single
// pixel tall. Otherwise, the titlebar will be visible underneath controls with
// vintage opacity set.
//
// We can't set it to all 0's unfortunately.
if (_borderless)
{
margins.cyTopHeight = 1;
}
else if (_GetTopBorderHeight() != 0)
{
RECT frame = {};
winrt::check_bool(::AdjustWindowRectExForDpi(&frame, GetWindowStyle(_window.get()), FALSE, 0, _currentDpi));
@ -896,6 +905,10 @@ void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled)
_titlebar.Visibility(_IsTitlebarVisible() ? Visibility::Visible : Visibility::Collapsed);
}
// Update the margins when entering/leaving focus mode, so we can prevent
// the titlebar from showing through transparent terminal controls
_UpdateFrameMargins();
// GH#4224 - When the auto-hide taskbar setting is enabled, then we don't
// always get another window message to trigger us to remove the drag bar.
// So, make sure to update the size of the drag region here, so that it

View File

@ -128,7 +128,7 @@
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.3.210521003\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.3.210521003\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.4.210908001\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.4.210908001\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets'))" />
</Target>
<!-- Override GetPackagingOutputs to roll up all our dependencies.
@ -176,5 +176,5 @@
<!-- **END VC LIBS HACK** -->
</Target>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
<Import Project="..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.3.210521003\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.3.210521003\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets')" />
</Project>
<Import Project="..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.4.210908001\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Microsoft.Internal.Windows.Terminal.ThemeHelpers.0.4.210908001\build\native\Microsoft.Internal.Windows.Terminal.ThemeHelpers.targets')" />
</Project>

View File

@ -3,6 +3,6 @@
<package id="Microsoft.Windows.CppWinRT" version="2.0.210825.3" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.5.0-prerelease.201202003" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.3.210521003" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.4" targetFramework="native" />
<package id="Microsoft.Internal.Windows.Terminal.ThemeHelpers" version="0.4.210908001" targetFramework="native" />
</packages>

View File

@ -67,6 +67,7 @@ Abstract:
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.ApplicationModel.Resources.Core.h>
#include <winrt/Windows.UI.Composition.h>
#include <winrt/TerminalApp.h>
#include <winrt/Microsoft.Terminal.Settings.Model.h>