From 694c6b263ff4a85a4f595cc3bd88d426bf822694 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 7 Oct 2021 06:39:20 -0500 Subject: [PATCH] When enabling opacity on win10, automatically enable acrylic (#11372) In #11180 we made `opacity` independent from `useAcrylic`. We also changed the mouse wheel behavior to only change opacity, and not mess with acrylic. However, on Windows 10, vintage opacity doesn't work at all. So there, we still need to manually enable acrylic when the user requests opacity. * [x] Closes #11285 SUI changes in action: ![auto-acrylic-win10](https://user-images.githubusercontent.com/18356694/136281935-db9a10f4-e0ad-4422-950b-0a01dc3e12c0.gif) --- src/cascadia/TerminalControl/ControlCore.cpp | 35 +++++++++++++++++++ src/cascadia/TerminalControl/ControlCore.h | 2 ++ .../TerminalSettingsEditor/Profiles.cpp | 16 +++++++++ .../TerminalSettingsEditor/Profiles.h | 14 ++++++++ .../UnitTests_Control/ControlCoreTests.cpp | 7 ++-- .../ControlInteractivityTests.cpp | 6 ++-- 6 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 9c3af6bc3..c287cdbd7 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -442,6 +442,17 @@ namespace winrt::Microsoft::Terminal::Control::implementation _settings.Opacity(newOpacity); + // GH#11285 - If the user is on Windows 10, and they changed the + // transparency of the control s.t. it should be partially opaque, then + // opt them in to acrylic. It's the only way to have transparency on + // Windows 10. + // We'll also turn the acrylic back off when they're fully opaque, which + // is what the Terminal did prior to 1.12. + if (!IsVintageOpacityAvailable()) + { + _settings.UseAcrylic(newOpacity < 1.0); + } + auto eventArgs = winrt::make_self(newOpacity); _TransparencyChangedHandlers(*this, *eventArgs); } @@ -570,6 +581,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation _settings = settings; + // GH#11285 - If the user is on Windows 10, and they wanted opacity, but + // didn't explicitly request acrylic, then opt them in to acrylic. + // On Windows 11+, this isn't needed, because we can have vintage opacity. + if (!IsVintageOpacityAvailable() && _settings.Opacity() < 1.0 && !_settings.UseAcrylic()) + { + _settings.UseAcrylic(true); + } + // Initialize our font information. const auto fontFace = _settings.FontFace(); const short fontHeight = ::base::saturated_cast(_settings.FontSize()); @@ -1545,4 +1564,20 @@ namespace winrt::Microsoft::Terminal::Control::implementation return hstring(ss.str()); } + + // Helper to check if we're on Windows 11 or not. This is used to check if + // we need to use acrylic to achieve transparency, because vintage opacity + // doesn't work in islands on win10. + // Remove when we can remove the rest of GH#11285 + bool ControlCore::IsVintageOpacityAvailable() noexcept + { + OSVERSIONINFOEXW osver{}; + osver.dwOSVersionInfoSize = sizeof(osver); + osver.dwBuildNumber = 22000; + + DWORDLONG dwlConditionMask = 0; + VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); + + return VerifyVersionInfoW(&osver, VER_BUILDNUMBER, dwlConditionMask) != FALSE; + } } diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index a04032ef7..9b96f6c7e 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -149,6 +149,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation hstring ReadEntireBuffer() const; + static bool IsVintageOpacityAvailable() noexcept; + // -------------------------------- WinRT Events --------------------------------- // clang-format off WINRT_CALLBACK(FontSizeChanged, Control::FontSizeChangedEventArgs); diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.cpp b/src/cascadia/TerminalSettingsEditor/Profiles.cpp index 8e43f9b10..6c507ecf4 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.cpp +++ b/src/cascadia/TerminalSettingsEditor/Profiles.cpp @@ -47,6 +47,22 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation // NOTE: this is similar to what is done with BackgroundImagePath above _NotifyChanges(L"UseParentProcessDirectory", L"UseCustomStartingDirectory"); } + else if (viewModelProperty == L"UseAcrylic") + { + // GH#11372: If we're on Windows 10, and someone turns off + // acrylic, we're going to disable opacity for them. Opacity + // doesn't work without acrylic on Windows 10. + // + // BODGY: CascadiaSettings's function IsDefaultTerminalAvailable + // is basically a "are we on Windows 11" check, because defterm + // only works on Win11. So we'll use that. + // + // Remove when we can remove the rest of GH#11285 + if (!UseAcrylic() && !CascadiaSettings::IsDefaultTerminalAvailable()) + { + Opacity(1.0); + } + } }); // Do the same for the starting directory diff --git a/src/cascadia/TerminalSettingsEditor/Profiles.h b/src/cascadia/TerminalSettingsEditor/Profiles.h index 74c31e49a..161f84e39 100644 --- a/src/cascadia/TerminalSettingsEditor/Profiles.h +++ b/src/cascadia/TerminalSettingsEditor/Profiles.h @@ -23,6 +23,20 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation void SetAcrylicOpacityPercentageValue(double value) { Opacity(winrt::Microsoft::Terminal::Settings::Editor::Converters::PercentageValueToPercentage(value)); + + // GH#11372: If we're on Windows 10, and someone wants opacity, then + // we'll turn acrylic on for them. Opacity doesn't work without + // acrylic on Windows 10. + // + // BODGY: CascadiaSettings's function IsDefaultTerminalAvailable + // is basically a "are we on Windows 11" check, because defterm + // only works on Win11. So we'll use that. + // + // Remove when we can remove the rest of GH#11285 + if (value < 100.0 && winrt::Microsoft::Terminal::Settings::Model::CascadiaSettings::IsDefaultTerminalAvailable()) + { + UseAcrylic(true); + } }; void SetPadding(double value) diff --git a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp index 9e4a19e7b..4c090b27e 100644 --- a/src/cascadia/UnitTests_Control/ControlCoreTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlCoreTests.cpp @@ -139,8 +139,11 @@ namespace ControlUnitTests // GH#603: Adjusting opacity shouldn't change whether or not we // requested acrylic. - VERIFY_IS_TRUE(settings->UseAcrylic()); - VERIFY_IS_TRUE(core->_settings.UseAcrylic()); + + auto expectedUseAcrylic = winrt::Microsoft::Terminal::Control::implementation::ControlCore::IsVintageOpacityAvailable() ? true : + (expectedOpacity < 1.0 ? true : false); + VERIFY_ARE_EQUAL(expectedUseAcrylic, settings->UseAcrylic()); + VERIFY_ARE_EQUAL(expectedUseAcrylic, core->_settings.UseAcrylic()); }; core->TransparencyChanged(opacityCallback); diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index db1e07435..51a2215e9 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -119,8 +119,10 @@ namespace ControlUnitTests VERIFY_ARE_EQUAL(expectedOpacity, settings->Opacity()); VERIFY_ARE_EQUAL(expectedOpacity, core->_settings.Opacity()); - VERIFY_ARE_EQUAL(useAcrylic, settings->UseAcrylic()); - VERIFY_ARE_EQUAL(useAcrylic, core->_settings.UseAcrylic()); + auto expectedUseAcrylic = winrt::Microsoft::Terminal::Control::implementation::ControlCore::IsVintageOpacityAvailable() ? useAcrylic : + (expectedOpacity < 1.0 ? true : false); + VERIFY_ARE_EQUAL(expectedUseAcrylic, settings->UseAcrylic()); + VERIFY_ARE_EQUAL(expectedUseAcrylic, core->_settings.UseAcrylic()); }; core->TransparencyChanged(opacityCallback);