diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index efcce89c84f..c2f88fb5105 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 a04032ef78e..9b96f6c7e48 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 8e43f9b10fc..6c507ecf456 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 74c31e49a16..161f84e39f1 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 9e4a19e7b50..4c090b27e71 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 db1e0743580..51a2215e915 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);